Как очистить UITextView с помощью пользовательского NSTextStorage? [только iOS7]

В настоящее время я пытаюсь создать экран, похожий на SMS, где пользователь может написать текст и отправить его другим пользователям. Все идет так, как ожидалось, пока я не попытаюсь очистить свое текстовое представление и не столкнусь с ошибкой. Я пытался найти способ обойти эту проблему, но я просто не могу найти достаточно документации в Интернете. Итак, вот оно, и, надеюсь, один из вас знает, как это исправить.


Реализация

Мой UITextView является подклассом реализации Питера Стейнбергера для iOS7, и я использую его с пользовательским подклассом NSTextStorage, как показано в objc.io «Знакомство с TextKit», и особенно с этим исходный код для выделения имен пользователей в сообщении.

В моем ViewController я настраиваю свое текстовое хранилище следующим образом:

self.textStorage = [[[MyCustomTextStorage alloc] init] autorelease]; [self.textStorage addLayoutManager:self.textView.layoutManager];

А затем в моем методе делегата TextView:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text

Я сохраняю ввод в своем пользовательском TextStorage:

[self.textStorage.string stringByReplacingCharactersInRange:range withString:text];

Авария

Я могу получить свой текст через self.textStorage.string, а затем очистить свое текстовое представление, заменив символы в диапазоне входной строки. Это работает довольно хорошо, но когда я снова пытаюсь установить TextView в качестве первого ответчика, приложение падает.

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSCFString _getBlockStart:end:contentsEnd:forRange:stopAtLineSeparators:]: Range {5, 0} out of bounds; string length 0'

Упомянутый диапазон - это диапазон моей ранее очищенной строки, поэтому похоже, что я могу очистить дисплей, но мой TextStorage/TextView сохраняет ссылку на первый отредактированный диапазон/строку.


Любая идея о том, что может быть причиной этого сбоя и как его решить? Спасибо за внимание; на данный момент любая помощь приветствуется, поэтому, пожалуйста, не стесняйтесь публиковать, если у вас есть совет. :)


person Julien    schedule 13.01.2014    source источник


Ответы (3)


Причина сбоя заключается в том, что вы используете диапазон, который находится за пределами строки в textStorage. Если вы хотите очистить textView, почему бы просто не использовать self.textStorage.string=@""

person Duncan Groenewald    schedule 16.01.2014
comment
Привет, я уже пробовал это, но произошел тот же сбой ... - person Julien; 16.01.2014
comment
Вероятно, вам не следует устанавливать textStorage.string в методе делегата shouldChangeTextInRange. Вы должны только исправить текст в переданном параметре и вернуть YES. - person Duncan Groenewald; 17.01.2014

Такая же ситуация и у вас.

На ее решение у меня ушло полдня.

  1. Пример, который вы приводите, правильный.

  2. Ваше приложение будет аварийно завершать работу не только при его очистке, но и при каждом использовании -setText:.

  3. Они не разбиваются, потому что никогда не позвонят -setText:!!!

Решение:

добавьте в свой код все необходимые кадры TextKit,

нравится:

_textStorage = [[NSTextStorage alloc] init];
_layoutManager = [[NSLayoutManager alloc] init];
[_textStorage addLayoutManager:_layoutManager];
_textContainer = [[NSTextContainer alloc] init];
[_layoutManager addTextContainer:_textContainer];
_myTextView = [[UITextView alloc] initWithFrame:frame textContainer:_textContainer];

На самом деле, вы пропустили NSTextContainer, поэтому нет подходящего контейнера для вставки строки, после чего приложение разбилось.

Может быть, вы можете отправить запросы на включение в эти два демо-проекта, чтобы не пропустить других людей.

person Croath    schedule 17.04.2014

После замены текста попробуйте:

[self setSelectedRange:NSMakeRange(0, 0)];
person Winston Chen    schedule 20.10.2014