Производительность основного текста

Я вижу некоторые проблемы с производительностью с Core Text, когда он запускается на оригинальном iPad.

Я создал редактируемый вид, используя Core Text и протокол UITextInput, основанный на OmniGroup OUIEditableFrame.

Когда в представлении имеется достаточное количество текста, скажем 180 строк, ввод/ввод значительно отстает, а одно нажатие на клавишу обычно занимает 1-2 секунды.

Используя инструменты с симулятором, я смог сузить проблему и узнать, что было так много времени. Оказывается, потому что я перерисовываю кадр с каждым нажатием клавиши, то, что занимает так много времени, вызывает CTFramesetterCreateWithAttributedString и CTFramesetterCreateFrame.

Мне нужно перерисовать с каждым штрихом клавиши, чтобы текст обновлялся, это означает вызов CTFramesetterCreateWithAttributedString и CTFramesetterCreateFrame.

Кто-нибудь еще сталкивается с этой проблемой, и если да, то как они обошли это?


EDIT:

Дальнейшее исследование и выяснилось, что если атрибутная строка не имеет атрибутов, то все становится намного быстрее и без какого-либо отставания. Изменение стиля шрифта, цвета или абзацев замедляет его. Любая идея, если это может иметь к этому какое-то отношение?

Ответы

Ответ 1

С моего первоначального вопроса я сделал еще несколько исследований и выяснил, что чем больше атрибутов имеет рисованная строка, тем дольше это требуется.

С этими знаниями я решил просто удалить/скрыть любые атрибуты (в частности, kCTForegroundColor), которые пользователь не смог увидеть, это ускорило рисунок в десять раз и сделало его более удобным для использования.

Ответ 2

Вероятно, вы не должны использовать CTFramesetter для создания чего-то вроде UITextView. Вместо этого вы должны сохранить массив ссылок CTLine. Если вам нужна помощь при разрыве слов, вы можете использовать CTTypeSetter, но вам нужно всего лишь передать строки в текущем карете и ниже (вы все равно будете создавать и уничтожать наборщиц немного, поэтому смотрите, сколько вы просите из них).

Одна хорошая вещь по сохранению массива CTLines заключается в том, что вы можете выбросить те, которые вам не нужны, если у вас мало памяти и позже их восстановите. Просто отслеживайте диапазон символов для каждой строки.

Ответ 3

Альтернативный подход заключается в том, чтобы продолжать использовать CTFramesetter, но использовать меньшие CTFrames. Просто ваш NSAttributedString в подстроки (например, используя [NSString paragraphRangeForRange:], чтобы получить диапазоны абзацев, а затем сломать свою атрибутированную строку, используя атрибутSubstringFromRange:). Затем создайте CTFrame для каждого абзаца. Когда что-то изменяется (например, пользователь вводит что-то), вы только обновляете CTFrame (s), которые изменились.

Это означает, что вы должны продолжать использовать то, что CTFramesetter дает вам без снижения производительности при повторном настройке всего текста каждый раз.

Ответ 4

Я экспериментировал с использованием CTLines и UITableView в моих попытках сделать подсветку синтаксиса в iOS. Самое замечательное в tableView заключается в том, что вы можете обновлять, удалять и вставлять строку и только перерисовывать эту строку.

CTFramesetterCreateWithAttributedString очень медленный. Таким образом, чем меньше вы используете его, тем лучше. Если пользователь вводит что-то, вам не нужно снова разбивать весь текст на строки, вы можете просто обновить текущую строку, и если ее переполнение вы сможете вставить новый. Это небольшая работа, позволяющая работать в каждом случае, но производительность может быть потрясающей.

Это то, что я сделал: https://github.com/Anviking/Chromatism.