- [CALayer setNeedsDisplayInRect:] вызывает перерисовку всего слоя - PullRequest
7 голосов
/ 21 марта 2012

Я делаю CALayer на подклассы, чтобы предоставить свой собственный метод рисования.Для оптимизации я звоню -[MyLayer setNeedsDisplayInRect:] вместо -[MyLayer setNeedsDisplay].В методе рисования я получаю прямоугольник, который должен быть перерисован с помощью CGContextGetClipBoundingBox().

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

Любые идеи?

[EDIT]

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

Теперь я буду рендерить в контекст изображения и сохраню это изображение в качестве кэша.В методе рисования я буду отображать только кэшированное изображение.

1 Ответ

6 голосов
/ 25 октября 2012

Документация Apple, к сожалению, конфликтует, так как документы на -setNeedsDisplayInRect не указывают, работает ли метод на практике. Основываясь на моем собственном опыте, этот technote уточняет:

Обратите внимание, что из-за того, как iPhone / iPod touch / iPad обновляет свой экран, весь вид будет перерисован, если вы вызовете -setNeedsDisplayInRect: или -setNeedsDisplay:.

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

  • Если вы рисуете изображения, самое большое улучшение производительности, которое вы можете сделать, это использовать изображения тех же размеров, на которых вы рисуете. Если это не так, попробуйте кэшировать ваше изображение, отобразив его в некотором закадровом контексте растрового изображения и вернув его позже.
  • Проверьте свойство shouldRasterize на CALayer. Это может быть удачей, если вы пытаетесь манипулировать слоем, чьи подслои потенциально составляют сложную иерархию слоев. Обязательно проверьте, как у вас дела в инструментах, отметив флажок Color Hits Green and Misses Red в инструменте Core Animation. Если вы видите много красного, скорее всего, использование shouldRasterize причиняет больший вред, чем помогает.
  • Даже лучше, чем shouldRasterize, это сгладить иерархию слоев, поскольку тогда вы сможете избежать дополнительных издержек, которые shouldRasterize возникают при сглаживании иерархии слоев в реальном времени. Конечно, это не всегда возможно, но не бойтесь попробовать:)
  • Если вы рисуете изображения, попробуйте поэкспериментировать с режимом смешивания . Если вы рисуете непрозрачные изображения, вам не нужно использовать обычные методы с исходным кодом (которые используют пропускную способность для чтения / записи). Попробуйте kCGBlendModeCopy, который позволяет устранить накладные расходы на пропускную способность чтения.
  • Проверьте CGLayerRef, который позволяет вам кэшировать вывод Core Graphics при различных вызовах ваших методов рисования. Мой опыт показывает, что, если вы не делаете какое-то жесткое пиксельное нажатие, это оказывается более дорогостоящим, чем просто перерисовка. См. this для интересного прочтения.
  • Прежде всего, Инструменты - твой друг. Посмотрите пару видео с прошлых WWDC ( 2012, 2011 и 2010 ); все они имеют отличную информацию о том, как точно настроить производительность.

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

...