Search code examples
iosobjective-cnsmutableattributedstring

NSMutableAttributedString can't setAttributes or addAttributes correctly


I have a method below that I want to use to change the color of the last 6 characters of a UILabel's text, which will be a date in parenthesis, i.e. (1999). First I set the text of a tableViewCell and then I get the attributedText property so I can get the font and size of the UILabel text. I'm not sure what I'm doing wrong, but right now the whole string is yellow, not just the last 6 characters of the label's text. Any ideas why?

tableViewCell.titleLabel.text = speech.title;

NSAttributedString *titleAttributedString = tableViewCell.titleLabel.attributedText;
tableViewCell.titleLabel.attributedText = [speech titleAttributedString:titleAttributedString size:tableCell.titleLabel.font.pointSize];

// Speech class instance method
- (NSAttributedString *)titleAttributedString:(NSAttributedString *)attributedString size:(CGFloat)size {
    NSRange range = NSMakeRange(attributedString.length - 6, 6);
    NSMutableAttributedString *titleString = [attributedString mutableCopy];

    NSDictionary *titleAttributesDictionary = [attributedString attributesAtIndex:0 effectiveRange:&range];
    NSDictionary *dateAttributesDictionary  = @{
                                                NSFontAttributeName : titleAttributesDictionary[NSFontAttributeName],
                                                NSForegroundColorAttributeName : [UIColor yellowColor]
                                                };

    // Neither of these lines solves the problem
    // Both titleStrings are yellow
    [titleString setAttributes:dateAttributesDictionary range:range];
    [titleString addAttributes:dateAttributesDictionary range:range];
    [titleString setAttributes:dateAttributesDictionary range:range];

    return titleString;
}

Solution

  • You are overwriting your calculated range value in the attributesAtIndex:effectiveRange: call. That call asks for the attributes at index 0 and the effective range over which those attributes apply, which is your whole string. Just pass NULL for the effectiveRange: argument, as per the docs when you are not interested in the value (you're just after the font at index 0).

    HTH