Changing an Attributed String

NSMutableAttributedString declares a number of methods for changing both characters and attributes. You must take care not to modify attribute values after they have been passed to an attributed string. You may also need to repair inconsistencies that can be introduced if you modify an attributed string.

Modifying Attributes

NSMutableAttributedString declares a number of methods for changing both characters and attributes, such as the primitive replaceCharactersInRange:withString: and setAttributes:range:, or the more convenient methods addAttribute:value:range:, applyFontTraits:range:, and so on.

The following example illustrates how to specify a link attribute for a selected range in an attributed string, underline the text, and color it blue. Note that you can define whatever value you want for the link attribute, it is up to you to interpret the value when the link is selected—see Accessing Attributes—typically, however, you use either a string or a URL. For an explanation of the role of beginEditing and endEditing (shown in the sample), see Fixing Inconsistencies.

NSMutableAttributedString *string; // assume string exists
NSRange selectedRange; // assume this is set
 
NSURL *linkURL = [NSURL URLWithString:@"http://www.apple.com/"];
 
[string beginEditing];
[string addAttribute:NSLinkAttributeName
               value:linkURL
               range:selectedRange];
 
[string addAttribute:NSForegroundColorAttributeName
               value:[NSColor blueColor]
               range:selectedRange];
 
[string addAttribute:NSUnderlineStyleAttributeName
               value:[NSNumber numberWithInt:NSSingleUnderlineStyle]
               range:selectedRange];
[string endEditing];

Attribute values assigned to an attributed string become the property of that string, and should not be modified “behind the attributed string” by other objects. Doing so can render inconsistent the attributed string’s internal state. There are two main reasons for this:

If you must change attribute values, and are sure that the change will apply to the correct range, there are two strategies you can adopt:

Fixing Inconsistencies

All of the methods for changing a mutable attributed string properly update the mapping between characters and attributes, but after a change some inconsistencies can develop. Here are some examples of attribute consistency requirements:

The Application Kit’s extensions to NSMutableAttributedString define methods to fix these inconsistencies as changes are made. This allows the attributes to be cleaned up at a low level, hiding potential problems from higher levels and providing for very clean update of display as attributes change. There are four methods for fixing attributes and two to group editing changes:

The first method, fixAttributesInRange:, invokes the other three fix... methods to clean up deleted attachment references, font attributes, and paragraph attributes, respectively. The individual method descriptions explain what cleanup entails for each case.

NSMutableAttributedString provides beginEditing and endEditing methods for subclasses of NSMutableAttributedString to override. These methods allow instances of a subclass to record or buffer groups of changes and clean themselves up on receiving an endEditing message. The endEditing method also allows the receiver to notify any observers that it has been changed. NSTextStorage’s implementation of endEditing, for example, fixes changed attributes and then notifies its layout managers that they need to re-lay and redisplay their text. The default implementations do nothing.