Текст Какао - обновляющий текст на лету - PullRequest
3 голосов
/ 25 июня 2011

В приложении, над которым я работаю, пользователь вводит простой текст, и приложение форматирует текст, преобразовывая его в NSAttributedString, и отображает его. Все это происходит в прямом эфире.

В настоящее время я выполняю следующие действия в методе делегата textDidChange моего NSTextView:

- (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);
}

Хотя это в основном работает, это не идеально. Текст, кажется, мигает в течение доли секунды (вы особенно заметили это на красных точках при орфографических ошибках), и когда курсор был ранее около одного из краев видимого прямоугольника, позиция прокрутки сбрасывается. В моем случае это очень нежелательный побочный эффект.

Итак, мой вопрос: есть ли лучший способ сделать то, что я пытаюсь сделать?

1 Ответ

5 голосов
/ 26 июня 2011

Я думаю, у вас есть небольшое неправильное представление о том, как работает 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];
}
...