I have a custom NSTextView subclass, with a custom NSTextStorage component as well. The NSTextStorage modifies the text entered by the user based on context.
Because it's possible that the final text will be shorter than the text originally entered by the user, I had to override insertText:replacementRange
in my NSTextView. A minimum example is:
- (void) insertText:(id)string replacementRange:(NSRange)replacementRange {
if ([self hasMarkedText]) {
[[self textStorage] replaceCharactersInRange:[self markedRange] withString:string];
} else {
[[self textStorage] replaceCharactersInRange:[self selectedRange] withString:string];
}
[self didChangeText];
}
This works fine in extensive testing over several months.... Except that automatic spell checking and correction is disabled. The "squigglies" don't appear under misspelled words, unless I stop typing, move the mouse, and switch focus to and from my app. After several seconds, the entire textview is spellcheck'ed. Because it happens after the fact, automatic correction is disabled of course.
If I disable my custom insertText:replacementRange:
method, everything else works fine, and automatic spelling functionality returns. I just have to be careful not to trigger a change that results in shortening the text, as it triggers attribute out of range errors (the original reason for my custom method in the first place.)
Apparently Apple's implementation of insertText:replacementRange:
does much more than mine. I have tried multiple variations on [self checkTextInRange...]
, [self checkTextInSelection:]
, etc. None of them restore proper functionality.
Searching Apple's documentation doesn't help point me towards what I am leaving out from my method that is causing spell checking to break. Any pointers or ideas would be much appreciated!!
Thanks in advance!
EDIT: Here are some examples of the sorts of behavior my NSTextStorage provides. (|
represents the insertion caret)
Starting with:
* item
* |
If I hit the return key, I end up with the following (deleting *<space>
):
* item
|
Another example, if "Change Tracking" is enabled:
this is thee| time
If I hit delete:
this is the|{--e--} time
As you can see, a single keystroke may result in the addition or deletion of multiple characters from the text.
EDIT 2: FYI -- the issue I have with attributes being out of range occur when the shortening happens while pressing return at the end of the document -- NSTextview attempts to set a new paragraph style only to find that the document is shorter than expected. I can find no way to change the range NSTextview targets.
beginEditing
,endEditing
,edited:range:changeInLength:
or something? – WillekeinsertText:replacementRange:
(but still using my custom NSTextStorage) and spelling returns. – Fletcher T. PenneyinsertText:replacementRange:
. Where do the errors come from? – WillekeinsertText...
method, it requests the attributes from NSTextStorage, expecting that the string is longer than it is. I tried sending back fake attributes, but that compounded the problem. By overriding the method, I left out the broken part, but apparently left out something I want as well.... ;) – Fletcher T. PenneyNSTextStorage
andNSTextStorageDelegate
do you modify the text? – Willeke