Search code examples
ioscore-textnsattributedstring

Does NSMutableAttributedString automatically concatenate identical adjacent attributes?


We have a simple markup parser in our iOS app that takes text with HTML-like tags and converts it into an NSAttributedString by iterating over each character in a simple NSString and producing an NSMutableAttributedString.

In a worst case scenario where we added a new set of attributes to every single character as we iterated through a string, would the NSMutableAttributedString be intelligent enough to join the identical adjacent attribute ranges together and optimize? Or would it be horribly inefficient and slow to render in Core Text?

I'm not suggesting this is a good algorithm in general! I'm just looking at a worst case scenario, and wondering whether the NSMutableAttributedString has any built in intelligent behaviour?


Solution

  • I just tried something like this (a simplified version of my real code):

    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Testfoobarhey"];
    UIFont *font = [UIFont fontWithName:@"Georgia-Bold" size:12.0];
    [text addAttribute:NSFontAttributeName value:font range:NSMakeRange(4, 3)];
    [text addAttribute:NSFontAttributeName value:font range:NSMakeRange(7, 3)];
    

    In other words, I added two bold attributes right next to each other. Then I viewed the result:

    NSLog(@"%@", text);
    

    And the output showed three chunks of text: "Test" in normal font, "foobar" in bold, and "hey" in normal font.

    So to answer your question, yes, it looks like the two adjacent formatting ranges were joined automatically in the NSMutableAttributedString.

    P.S. On a related note, I've noticed that if I apply an attribute with a range that extends across a line break, the resulting NSAttributedString will have one attribute before the line break and another after, and the line break itself won't have any attributes. So if you're ever parsing one character at a time, you might need to compensate for that.