开发者

Cocoa Text - refreshing text on-the-fly

开发者 https://www.devze.com 2023-03-15 19:54 出处:网络
In an app I\'m working on, the user inputs plain text, and the app reformats the text by transforming it to an NSAttributedString, and displays it. This all happens live.

In an app I'm working on, the user inputs plain text, and the app reformats the text by transforming it to an NSAttributedString, and displays it. This all happens live.

Currently, I'm doing the following on my NSTextView's textDidChange delegate method:

- (void)textDidChange:(NSNotification *)notification {

    // saving the cursor position
    NSInteger insertionPoint = [[[self.mainTextView selectedRanges] objectAtIndex:0] rangeValue].location;

    // this grabs the text view's contact as plain text
    [self updateContentFromTextView];

    // this creates an attributed strings and displays it
    [self updateTextViewFromContent];

    // resetting the cursor position
    self.mainTextView.selectedRange = NSMakeRange(insertionPoint, 0);
}

While this mostly works, it's not ideal. The text seems to blink for a split second (you especially notice it on the red dots under spelling errors), and when the c开发者_如何学运维ursor was previously near one of the edges of the visible rect, it the scroll position gets reset. In my case, this is a very much undesirable side-effect.

So my question is: Is there a better way of doing what I'm trying to do?


I think you have a slight misconception of how an NSTextView works. The user never enters a "plain string", the data store of an NSTextView is always an NSTextStorage object, which is a subclass of NSMutableAttributedString.

What you need to do is add/remove attributes to the existing attributed string that the user is editing, rather than replacing the entire string.

You should also not make changes to the string in the ‑textDidChange: delegate method, as changing the string from that method can cause another change notification.

Instead, you should implement the delegate method ‑textStorageDidProcessEditing:. This is called whenever the text changes. You can then make modifications to the string like so:

- (void)textStorageDidProcessEditing:(NSNotification*)notification
{
    //get the text storage object from the notification
    NSTextStorage* textStorage = [notification object];

    //get the range of the entire run of text
    NSRange aRange = NSMakeRange(0, [textStorage length]);

    //for example purposes, change all the text to yellow

    //remove existing coloring
    [textStorage removeAttribute:NSForegroundColorAttributeName range:aRange];

    //add new coloring
    [textStorage addAttribute:NSForegroundColorAttributeName 
                        value:[NSColor yellowColor] 
                        range:aRange];
}
0

精彩评论

暂无评论...
验证码 换一张
取 消