Fixed it! What I ended up doing was adding an instance variable tempAttributes
to my NSTextStorage subclass. If I tried to set the attributes of a string with range 0, I set tempAttributes
to the attributes being passed in. Then on the next pass of the method, if tempAttributes
had data, I set the range it was trying to change with that instead of the old attributes. New code:
- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range
{
NSLog(@"setAttributes:%@ range:%@", attrs, NSStringFromRange(range));
[self beginEditing];
if (range.location == _backingStore.length || range.length == 0) {
tempAttributes = attrs;
} else {
if (tempAttributes) {
[_backingStore setAttributes:tempAttributes range:range];
tempAttributes = nil;
} else {
[_backingStore setAttributes:attrs range:range];
}
}
[_backingStore fixAttributesInRange:range];
[self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
[self endEditing];
}