I'm writing an app that deals with rich text editing using a UITextView. It uses NSTextStorage to set new attributes for parts of the string. However, in the case that the user wants to change the font or font size at the end of the string for a new style of text or in the middle of the string (in other words when range passed to setAttributes:range:
has a length of 0) this can't be done because you can't set attributes with a range of 0. So basically, how can I set a new UIFont for the position of the cursor in a UITextView?
relevant code from my NSTextStorage subclass:
- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range
{
NSLog(@"setAttributes:%@ range:%@", attrs, NSStringFromRange(range));
[self beginEditing];
[_backingStore setAttributes:attrs range:range];
[_backingStore fixAttributesInRange:range];
[self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
[self endEditing];
}
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];
}