Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Underline part of a string using NSMutableAttributedString in iOS 8 is not working

I try to underline part of a string, for example, a 'string' part in 'test string' string. I'm using NSMutableAttributedString and my solution was working well on iOS7.

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc]         initWithString:@"test string"]; [attributedString addAttribute:NSUnderlineStyleAttributeName                          value:@(NSUnderlineStyleSingle)                          range:NSMakeRange(5, 6)]; myLabel.attributedText = attributedString; 

The problem is that my solution is not working in iOS8 anymore. After spending an hour on testing multiple variants of NSMutableAttributedString, I found out that this solution works only when range starts with 0 (length can differ). What is the reason for that? How can I workaround this?

like image 688
KlimczakM Avatar asked Oct 01 '14 07:10

KlimczakM


People also ask

How do you underline text in UILabel?

To make the text on UILabel underlined we will need to use the NSMutableAttributedString together with NSUnderlineStyleAttributeName. The Swift code snippet below demonstrates how to create a new UILabel programmatically and then use the NSMutableAttributedString to underline the text on the label.

How do you underline a word in Swift?

How do I underline a button in Swift? swift 3/4/5 Select button or label title as Attributed. Select range of text which you want to underline. Right click and choose Font then select underline.

What is NSAttributedString?

An NSAttributedString object manages character strings and associated sets of attributes (for example, font and kerning) that apply to individual characters or ranges of characters in the string. An association of characters and their attributes is called an attributed string.


2 Answers

Update: By investigating this question: Displaying NSMutableAttributedString on iOS 8 I finally found the solution!

You should add NSUnderlineStyleNone at the beginning of the string.

Swift 4.2 (none was removed):

let attributedString = NSMutableAttributedString() attributedString.append(NSAttributedString(string: "test ",                                            attributes: [.underlineStyle: 0])) attributedString.append(NSAttributedString(string: "s",                                            attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue])) attributedString.append(NSAttributedString(string: "tring",                                            attributes: [.underlineStyle: 0])) 

Objective-C:

 NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];  [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"test "                                                                           attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleNone)}]];  [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"s"                                                                          attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),                                                                                       NSBackgroundColorAttributeName: [UIColor clearColor]}]];  [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"tring"]]; 

Another bonus of such approach is absence of any ranges. Very nice for localized strings.

Seems like it is Apple bug :(

like image 76
kelin Avatar answered Oct 13 '22 07:10

kelin


I found that if you apply UnderlineStyleNone to the whole string you can then selectively apply underline to a part that starts in the middle:

func underlinedString(string: NSString, term: NSString) -> NSAttributedString {     let output = NSMutableAttributedString(string: string)     let underlineRange = string.rangeOfString(term)     output.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleNone.rawValue, range: NSMakeRange(0, string.length))     output.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: underlineRange)      return output } 
like image 43
exidy Avatar answered Oct 13 '22 08:10

exidy