I'm writing a syntax markdown for iOS/osx.
It's a subclass of NSTextStorage. It works great in iOS but in OSX (after converting the code, UIColor to NSColor and UIFont to NSFont) it does work very well. It works great if I write at the end of current line but if I change caret position to middle of text, just after typing 1 letter, it changes caret position to end of line. This just happens in OSX because in IOS it works great.
I know the problem is located in - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range
but don't know how to fix it... any help ?
- (NSString *)string {
return [_backingStore string];
}
- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range {
return [_backingStore attributesAtIndex:location effectiveRange:range];
}
- (void)replaceCharactersInRange:(NSRange)range withString:(NSString*)str {
[self beginEditing];
[_backingStore replaceCharactersInRange:range withString:str];
[self edited:NSTextStorageEditedCharacters | NSTextStorageEditedAttributes range:range changeInLength:str.length - range.length];
[self endEditing];
}
- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range {
[self beginEditing];
[_backingStore setAttributes:attrs range:range];
[self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
[self endEditing];
}
- (void)processEditing {
[self performReplacementsForRange:[self editedRange]];
[super processEditing];
}
- (void)performReplacementsForRange:(NSRange)changedRange {
NSString* backingString = [_backingStore string];
NSRange extendedRange = extendedRange = NSUnionRange(changedRange, [backingString lineRangeForRange:NSMakeRange(NSMaxRange(changedRange), 0)]);
[self applyStylesToRange:extendedRange];
}
- (void)applyStylesToRange:(NSRange)searchRange {
NSDictionary* attributeDictionary = self.attributeDictionary;
NSString* backingString = [_backingStore string];
NSDictionary* bodyAttributes = self.bodyAttributes;
[self setAttributes:bodyAttributes range:searchRange];
[attributeDictionary enumerateKeysAndObjectsUsingBlock:^(NSRegularExpression* regex, NSDictionary* attributes, BOOL* stop) {
[regex enumerateMatchesInString:backingString options:0 range:searchRange
usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) {
NSRange matchRange = [match rangeAtIndex:1];
[self addAttributes:attributes range:matchRange];
}];
}];
}
I'm not familiar with NSTextStorage but I managed to fix this by overriding
fixAttributesInRange:
instead ofprocessEditing
.Instead of
do
Btw: shouldn't
applyStylesToRange
be nested betweenbeginEditing
andendEditing
?