Drawrect Vs layoutsubviews - NSView - Cocoa touch

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

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

Спасибо

Ответы

Ответ 1

-layoutSubviews вызывается из -layoutIfNeeded, если был установлен флаг "Необходимый макет" (с использованием -setNeedsLayout или автоматически при изменении границ представления). Используйте его для позиционирования вашего представления [ EDIT: Используйте его для позиционирования подпунктов].

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

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

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

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

EDIT: И еще несколько подробностей, когда я проснулся:

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

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

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

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

Ответ 2

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

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

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

Удачи.