2011-06-25 30 views
3

在我正在处理的应用程序中,用户输入纯文本,应用程序通过将文本转换为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); 
} 

虽然这主要是工作,它的效果并不理想。文本似乎瞬间闪烁(尤其是在拼写错误下的红点上),并且当光标先前位于可见矩形的某个边缘附近时,滚动位置将被重置。就我而言,这是一个非常不理想的副作用。

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

回答

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]; 
} 
+0

无论何时进行文本更改(即键入字符),都会调用该方法。这是在提交更改之前修改文本存储对象的最后机会。这意味着您可以更改文本属性,但重要的是,不是文本本身。其中最常见的用法之一是语法着色。 –

+0

没错。它不适合我。注意我正在使用Lion API。不知道这是否会改变任何事情。对我来说,这种方法永远不会被调用。我看了看文档,看起来很好。虽然我没有做任何'beginEditing'和'endEditing',也许这就是它的一部分?我无论如何都给你接受,因为直接在'textDidChange'中直接使用你的代码就可以了。 –