18

I am working on a UILabel which features large main text followed by smaller text that tells you who said it:

Screenshot showing problem

Right now it is basically an NSAttributedString with a font attribute on the small text.

I would like to set things up so the big text wraps but the small text doesn't. I.e., If the text will all fit on the same line as it does in the right item, it should render as is, but it it would wrap like in the left item, the whole of the small text should appear on the next line:

Screenshot showing correct behavior

The HTML equivalent of what I'm trying to achieve is:

Title <nobr>Subtitle</nobr>
- or -
Title <span style="white-space:nowrap">Subtitle</span>

I've tried converting both of these to NSAttributedStrings with NSHTMLTextDocumentType and it doesn't appear to do a direct translation.

Brian Nickel
  • 26,890
  • 5
  • 80
  • 110
  • 7
    I haven't tried but what about replacing regular spaces (`\U0020`) with non-break spaces (`\U00A0`) in the part of the text you don't want to split up? – rmaddy Aug 19 '14 at 21:37

3 Answers3

33

Following rmaddy's suggestion, I was able to get the effect I wanted by replacing spaces and dashes with their non-breaking alternatives:

Objective-C:

NS_INLINE NSString *NOBR(NSString *string) {
return [[string stringByReplacingOccurrencesOfString:@" " withString:@"\u00a0"] 
                stringByReplacingOccurrencesOfString:@"-" withString:@"\u2011"];

}

NSAttributedString *username = [[NSAttributedString alloc] 
    initWithString:NOBR(hotQuestion.username) attributes:nil];
...

Swift (note the slightly different escape code format):

func nobr(_ string:String) -> String {
    return string
        .stringByReplacingOccurrencesOfString(" ", withString: "\u{a0}")
        .stringByReplacingOccurrencesOfString("-", withString: "\u{2011}")
}

let username = NSAttributedString(string:nobr(hotQuestion.username, attributes:nil))
Brian Nickel
  • 26,890
  • 5
  • 80
  • 110
16

There is also word-joiner \u2060 character in Unicode which will prevent line break on its either side and is invisible. I used it to force word wrap when degree sign was part of word, so the whole word will stay on the same line, in iOS.

Objective-C:

text = [text stringByReplacingOccurrencesOfString:@"°" withString:@"\u2060°\u2060"];
PetrV
  • 1,368
  • 2
  • 15
  • 30
4

@brian-nickel great solution in Swift 5.1 and in a String extension

extension String {
    var withoutLineBreak: String {
        self.replacingOccurrences(of: " ", with: "\u{a0}")
            .replacingOccurrences(of: "-", with: "\u{2011}")
    }
}
Thomas Besnehard
  • 2,106
  • 3
  • 25
  • 47