Cocoa Text - 即时刷新文本

Ken*_*ger 3 cocoa nstextview core-text

在我正在处理的应用程序中,用户输入纯文本,应用程序通过将文本转换为NSAttributedString来重新格式化文本,并显示它.一切都发生了.

目前,我在NSTextView的textDidChange委托方法上执行以下操作:

- (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);
}
Run Code Online (Sandbox Code Playgroud)

虽然这主要起作用,但并不理想.文本似乎瞬间闪烁(你特别注意拼写错误下的红点),当光标先前接近可见矩形的一个边缘时,滚动位置会重置.就我而言,这是一个非常不受欢迎的副作用.

所以我的问题是:有没有更好的方法来做我想做的事情?

Rob*_*ger 5

我认为你对如何NSTextView运作有一点误解.用户永远不会进入一个"纯字符串",的数据存储NSTextView总是一个NSTextStorage对象,它是的一个子类NSMutableAttributedString.

您需要做的是向用户正在编辑的现有属性字符串添加/删除属性,而不是替换整个字符串.

您也不应该在?textDidChange:委托方法中更改字符串,因为从该方法更改字符串可能会导致另一个更改通知.

相反,您应该实现委托方法?textStorageDidProcessEditing:.每当文本更改时都会调用此方法.然后,您可以像这样对字符串进行修改:

- (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];
}
Run Code Online (Sandbox Code Playgroud)