Drawrect Vs Layoutsubviews - NSView - Какао сенсорный - PullRequest
18 голосов
/ 24 сентября 2010

Я не могу найти достойный ответ, чтобы объяснить мне разницу между этими двумя функциями.когда каждый вызывается, и как одно отличается от другого?

Например, я не могу просто расположить свои взгляды внутри Drawrect?

Спасибо

Ответы [ 2 ]

57 голосов
/ 25 сентября 2010

-layoutSubviews вызывается из -layoutIfNeeded, если был установлен флаг «Требуется макет» (используется -setNeedsLayout или автоматически при изменении границ вида). Используйте его для позиционирования вашего вида [ РЕДАКТИРОВАТЬ: Используйте его для позиционирования подпредставлений ].

-drawRect: вызывается с -displayIfNeeded, если был установлен флаг «display display» (с использованием -setNeedsDisplay или автоматически, если вы установили view.contentMode = UIViewContentModeRedraw).

Оба -layoutIfNeeded и -displayIfNeeded автоматически вызываются UIKit / CoreAnimation перед тем, как что-либо выводится на экран; вам редко нужно звонить им напрямую.

Вы можете расположить свои подпредставления в -drawRect: (вы даже можете добавить подпредставления!), Но это неразумно:

  • По умолчанию -setNeedsDisplay не вызывается автоматически при изменении границ.
  • Реализация -drawRect: снижает производительность (UIKit / CoreAnimation должен создать для вас растровый графический контекст); делайте это только в том случае, если вам нужно выполнить пользовательский рисунок.
  • Вам нужно перерисовать представление в -drawRect:. Рисование стоит дорого. Перемещение взглядов дешево.
  • UIKit / CoreAnimation, вероятно, выполняет этап макета, за которым следует этап рисования. CoreAnimation может использовать информацию макета, чтобы решить, какие виды нужно рисовать (например, он может игнорировать виды, скрытые непрозрачными подпредставлениями, внеэкранными представлениями или подпредставлениями за пределами представления clipsToBounds = YES; или он может рисовать только под-прямоугольник большой вид). Если вы перемещаете виды во время прохождения рисования, CoreAnimation может отображать их неправильно.

РЕДАКТИРОВАТЬ: И еще некоторые подробности, когда я не сплю:

В чем разница между «показом» и «отрисовкой»? Отображение осуществляется с помощью -[CALayer display]; реализация по умолчанию (приблизительно)

  • Если представитель уровня отвечает на -displayLayer:, позвоните [self.delegate displayLayer:self]. -displayLayer: должен установить layer.content на (например) CGImage,
  • В противном случае, если делегат уровня отвечает на -drawLayer:inContext:, настройте контекст на основе растрового изображения, вызовите [self.delegate drawLayer:self inContext:context] и сохраните вывод в layer.content (вывод на самом деле является CABackingStore, который предположительно является частным API )
  • В противном случае не изменяйте layer.content.

Представление является делегатом слоя, поэтому вы можете вместо этого реализовать -[MyView displayLayer:] и делать интересные вещи, такие как

  • self.layer.contents = (id)([UIImage imageNamed:@"foo"].CGImage) (это примерно то, что делает UIImageView)
  • Нет, чтобы предотвратить любой "рисунок". Это может быть полезно, если вы подклассами, например UIToolbar и хочу дать ему прозрачный фон. (Это также предотвращает создание CGContext / CABackingStore.)
  • Перемещать подпредставления без снижения производительности (но это по-прежнему не очень хорошая идея по вышеуказанным причинам).
0 голосов
/ 25 сентября 2010

Возможно, у меня нет ответов на все вопросы, но я могу сказать вам, что: - layoutSubviews вызывается при изменении рамки просмотра - drawRect вызывается, когда setNeedDisplay вызывается

Большую часть времени вы не будете использовать layoutSubviews.

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

Удачи

...