Производительность основного текста
Я вижу некоторые проблемы с производительностью с 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.