Улучшение производительности рисования пальцами - PullRequest
1 голос
/ 31 августа 2009

Простая картина:
Перебирая экран iPhone, вы рисуете временную графику в UIView. Эта временная графика стирается после касания и затем сохраняется в базовом UIView.

Процесс прост:
1) Сенсорный запуск и перемещение >>
2) Рисование временной графики поверх UIView >>
3) Концы касания >>
4) Передача временной графики в базовый UIView >>
5) Базовый UIView добавляет временную графику к хранимой графике >>
6) Базовая UIView перерисовывает всю сохраненную графику >>
7) Удалить временную графику сверху UIView.

Таким образом, я могу накапливать графику в базовом UIView, сохраняя при этом отзывчивое рисование временной графики в верхнем UIView.

(Sidenote: каждый «Drawing» - это просто NSArray пользовательских «Point» объектов, которые являются просто контейнерами NSObject для CGPoints. А базовый UIView имеет отдельный NSArray, где он хранит эти NSArrays CGPoints)

Проблема в следующем:
Когда в базовом UIView накопилось много графики, требуется время, чтобы нарисовать все это на экране. И любые новые рисунки в верхнем UIView не будут отображаться, пока не будет завершено рисование лежащей в основе графики. Таким образом, при большом количестве графики на экране наблюдается заметная задержка.

Вопрос:
Кто-нибудь может придумать хороший способ повышения производительности, чтобы не было заметного лага между чертежами, когда на экране много графики?

Ответы [ 2 ]

2 голосов
/ 31 августа 2009

NSArray of CGPoints? Вы имеете в виду NSArray of NSValues ​​с CGPoints? Это невероятно дорогостоящий способ хранения огромного количества ценностей, к которым вы постоянно обращаетесь. Вы можете хранить эту информацию многими лучшими способами. Двумерный C-массив, представляющий весь экран, является наиболее очевидным. Вы также можете захотеть взглянуть на представления растровых изображений и рисовать непосредственно в CGImage, а не поддерживать кучу CGPoints. Взгляните на Quartz 2D Руководство по программированию .

EDIT:

Ваш объект (ниже) является эквивалентом NSValue, чуть более специализированным. Здесь много накладных расходов, когда у вас много-много объектов (~ 100 000, наверное, когда экран почти заполнен; больше, если вы не удаляете дубликаты; запустите Instruments для профилирования). Структуры данных старого стиля C, вероятно, будут намного быстрее для этого, потому что вы можете избежать всех сохранений / выпусков, распределений и т. Д. Однако есть и другие варианты. Проверка дубликатов точек будет намного быстрее с NSMutableSet, если вы выровняете пиксели CGPoints и перегружаете -isEqual вашего объекта Point.

Убедитесь, что вы выравниваете данные по пикселям. Рисование на дробных пикселях (и сохранение их всех) может значительно увеличить количество задействованных объектов и объем рисования, который вы делаете. Даже если вы хотите сглаживание, по крайней мере, округлите пиксели до .5 (или .25 или что-то ). CGPoint состоит из двух двойных. Вам не нужна такая точность, чтобы рисовать на экране.

1 голос
/ 31 августа 2009

Почему бы просто не нарисовать все в буфере CGBitmapContextRef, чтобы накапливались операции рисования, а затем нарисовать это на экране в вашем drawRect:? Вы сможете выполнять произвольные графические операции без замедления по мере увеличения общего числа операций.

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

...