I'm using iOS 6, so attributed strings should be easy to use, right? Well... not so much.
What I want to do:
Using a custom subclass of UIButton
(it doesn't do anything custom to titleLabel
), I'd like to have a multi-line, attributed title that is:
I've been able to get #'s 1 through 5 so far (at least, I thought I did, but current testing is yielding errors with multi-line text), but when I tried to do something (anything!) to get the text to be centered, my app keeps crashing. When I try to get all 6 items working (through various methods), I get the following crash/error:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason:
'NSAttributedString invalid for autoresizing,
it must have a single spanning paragraph style
(or none) with a non-wrapping lineBreakMode.'
Based on what I've tried, it appears that I can have one of the following options, but not both:
I can live with one or the other if I must, but I can't believe that I can't have what seems to be a fairly straightforward concept.
Can someone please tell me what I've got wrong?
Here's the last iteration of the code I'm trying:
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSTextAlignmentCenter];
[style setLineBreakMode:NSLineBreakByWordWrapping];
UIFont *font1 = [UIFont fontWithName:@"HelveticaNeue-Medium" size:20.0f];
UIFont *font2 = [UIFont fontWithName:@"HelveticaNeue-Light" size:20.0f];
NSDictionary *dict1 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle),
NSFontAttributeName:font1};
NSDictionary *dict2 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleNone),
NSFontAttributeName:font2};
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"LINE 1\n" attributes:dict1]];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"line 2" attributes:dict2]];
[[self buttonToStyle] setAttributedTitle:attString forState:UIControlStateNormal];
[[[self buttonToStyle] titleLabel] setNumberOfLines:0];
[[[self buttonToStyle] titleLabel] setLineBreakMode:NSLineBreakByWordWrapping];
It looks to me like you forgot in your code to use the "style" object that you set up.. you just instantiated it. You should modify your code to look like this:
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setAlignment:NSTextAlignmentCenter];
[style setLineBreakMode:NSLineBreakByWordWrapping];
UIFont *font1 = [UIFont fontWithName:@"HelveticaNeue-Medium" size:20.0f];
UIFont *font2 = [UIFont fontWithName:@"HelveticaNeue-Light" size:20.0f];
NSDictionary *dict1 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle),
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style}; // Added line
NSDictionary *dict2 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleNone),
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style}; // Added line
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"LINE 1\n" attributes:dict1]];
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"line 2" attributes:dict2]];
[self.resolveButton setAttributedTitle:attString forState:UIControlStateNormal];
[[self.resolveButton titleLabel] setNumberOfLines:0];
[[self.resolveButton titleLabel] setLineBreakMode:NSLineBreakByWordWrapping];
Note that I only added the lines that define the NSParagraphStyleAttributeName.. everything else is the same.. and this is what I get for the button:
And here it is in Swift 3.0
let style = NSMutableParagraphStyle()
style.alignment = .center
style.lineBreakMode = .byWordWrapping
guard
let font1 = UIFont(name: "HelveticaNeue-Medium", size: 20),
let font2 = UIFont(name: "HelveticaNeue-Light", size: 20) else { return }
let dict1:[String:Any] = [
NSUnderlineStyleAttributeName:NSUnderlineStyle.styleSingle.rawValue,
NSFontAttributeName:font1,
NSParagraphStyleAttributeName:style
]
let dict2:[String:Any] = [
NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue,
NSFontAttributeName:font2,
NSParagraphStyleAttributeName:style
]
let attString = NSMutableAttributedString()
attString.append(NSAttributedString(string: "LINE 1", attributes: dict1))
attString.append(NSAttributedString(string: "line 2", attributes: dict2))
button.setAttributedTitle(attString, for: .normal)
button.titleLabel?.numberOfLines = 0
button.titleLabel?.lineBreakMode = .byWordWrapping