I'm trying to create a subclass of UIButton that enforces text kerning. As such, when I build a button in Interface Builder, set the text colour (using plain text) I'm expecting to be able to take the existing text, colour, paragraph style, and font from the plain titleLabel
instance and translate it into an attributed label with the same properties.
I written two categories that I thought might help:
+ (NSMutableAttributedString*)attributedStringWithTitle:(NSString*)title fromExistingAttributedString:(NSAttributedString*)attributedString
{
NSDictionary *attributes = [attributedString attributesAtIndex:0 effectiveRange:NULL];
return [[NSMutableAttributedString alloc] initWithString:title attributes:attributes];
}
+ (NSMutableAttributedString*)attributedStringWithTitle:(NSString*)title fromPlainTextLabel:(UILabel*)label
{
NSMutableAttributedString* mutableTitle = [[NSMutableAttributedString alloc] initWithString:title];
[mutableTitle addAttribute:NSFontAttributeName value:label.font range:[mutableTitle fullRange]];
[mutableTitle addAttribute:NSForegroundColorAttributeName value:label.textColor range:[mutableTitle fullRange]];
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
style.alignment = label.textAlignment;
[mutableTitle addAttribute:NSParagraphStyleAttributeName value:style range:[mutableTitle fullRange]];
return mutableTitle;
}
And then in my UIButton subclass, I'm overriding these like so:
- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state
{
NSMutableAttributedString* mutableTitle = [title mutableCopy];
[mutableTitle addAttributes:@{NSKernAttributeName: @(kDefaultKerning)} range:[mutableTitle fullRange]];
[super setAttributedTitle:mutableTitle forState:state];
[self setNeedsDisplay];
}
- (void)setTitle:(NSString *)title forState:(UIControlState)state
{
NSMutableAttributedString* mutableTitle;
if ([self attributedTitleForState:state]) {
mutableTitle = [NSMutableAttributedString attributedStringWithTitle:title fromExistingAttributedString:[self attributedTitleForState:state]];
} else {
mutableTitle = [NSMutableAttributedString attributedStringWithTitle:title fromPlainTextLabel:self.titleLabel];
}
[self setAttributedTitle:mutableTitle forState:state];
}
But something's not working - particularly of note, [self attributedTitleForState:state]
and [self titleForState:state]
always seem to be nil. Seems to me like there's some disconnect in the way the properties are set in Interface Builder, in that while the text comes through OK, all of the styling is missing from it.