2011-06-25 68 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'中直接使用你的代碼就可以了。 –