UIView/CALayer: преобразование триггеров layoutSubviews в супервизии

При изменении некоторых свойств для UIView он вызывает layoutSubviews в супервизии. Я не могу найти никаких утверждений об этом в документах.

Эти свойства запускают макет в супервизии и self

  • рамка
  • Границы

Эти свойства запускают макет только в режиме просмотра только

  • преобразовать
  • layer.transform

Эти свойства запускают только макет только

  • ни один

Эти свойства не вызывают никакого макета

  • Центр
  • layer.anchorPoint
  • layer.position
  • альфа

Мне очень сложно понять, что преобразование запускает макет, и эта позиция и anchorPoint этого не делает.

Пример кода: https://github.com/hfossli/LayoutSubviewsInconsistency


Я хочу знать:

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

Я не могу найти ничего об этом в документах и ​​файлах заголовков. Проблема важна при использовании UIDynamics или аналогичного.

Ответ 1

Apple ответила мне через TSI (я лично считаю, что это мусор):

Часть 1

Почему я вижу это поведение? это непоследовательность или я не понимаю некоторые основные понятия?

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

почему он каскадирует вверх иерархию представлений?

Как правило, изменение геометрического свойства представления (или слоя) вызовет каскад недействительности макета вверх по иерархии представлений, поскольку родительские представления могут иметь ограничения Auto Layout с модифицированным дочерним элементом. Обратите внимание, что автоматический макет активен в какой-либо форме независимо от того, явно ли вы включили его.

как я могу избежать супервизора в layoutSubviews каждый раз, когда я изменяю преобразование?

Нельзя обойти это поведение. Это часть внутренней бухгалтерской документации UIKit, которая необходима для обеспечения согласованности иерархии представлений.

Часть 2

Привет Хэвард,

Но если это правда, я действительно не понимаю, почему это происходит не относится к "layer.anchorPoint" и "center" / "layer.position".

Возможно, в этом случае мы более консервативны. Родительские взгляды не должны заботиться о положении их детей, кроме случаев, когда задействован автоматический макет. И если бы была задействована автоматическая компоновка, вам нужно было бы изменить ограничения непосредственно, чтобы в любом случае произвести длительную настройку в позиции.

Это преобразование запускает layoutSubviews, который снова каскадирует вверх.

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

Любые идеи?

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

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