Search code examples
iosobjective-cuibuttoninterface-buildernsattributedstring

Overriding UIButton setAttributedTitle:forState:


I'm trying to override UIButton setAttributedTitle:forState: in order to set some default kerning everywhere the subclass is used. This code creates the correct NSAttributedString and works for any UIButtons I've created with Interface Builder:

- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state
{
    NSMutableAttributedString* attributeText = [[[NSAttributedString alloc] initWithAttributedString:title] mutableCopy];
    [attributeText addAttributes:@{NSKernAttributeName: @(kDefaultKerning)} range:[attributeText fullRange]];
    self.titleLabel.attributedText = attributeText;
    [self setNeedsDisplay];
}

But it doesn't work for any of the UIButton subclass that I create in code:

[_myButton setAttributedTitle:attributedString forState:UIControlStateNormal];

So I tried calling super instead of self.titleLabel.attributedText = attributeText;:

[super setAttributedTitle:title forState:state];

Which works for the button created in code, but now it doesn't work for the Interface Builder buttons.

Since as far as I know, Interface Builder just calls setAttributedText anyway, what gives? How can I get this override to work for both code-generated buttons and Interface Builder?


Solution

  • Silly me. Of course [super setAttributedTitle:title forState:state]; wasn't working, because I was setting it to title instead of attributedText.

    Solution:

    - (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state
    {
        NSMutableAttributedString* attributeText = [[[NSAttributedString alloc] initWithAttributedString:title] mutableCopy];
        [attributeText addAttributes:@{NSKernAttributeName: @(kDefaultKerning)} range:[attributeText fullRange]];
        [super setAttributedTitle:attributeText forState:state];
        [self setNeedsDisplay];
    }