Ответ 1
Редактор раскадровки (Interface Builder) сохраняет встроенный просмотр frame
в виде контейнера bounds
во время редактирования. Таким образом, когда раскадровка записывается в файл, сериализованные размеры представлений идентичны. Это происходит независимо от того, включена ли раскадровка в автоматическом макете.
В представлении верхнего уровня каждого контроллера представления в раскадровке также имеется маска для авторезистирования, установленная на UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
, снова независимо от того, включена ли раскадровка в автоматическом макете.
Если включена автоматическая компоновка, каждое представление верхнего уровня имеет translatesAutoresizingMaskToConstraints
значение YES
. Это отличается от всех потомков этих представлений верхнего уровня. У всех потомков translatesAutoresizingMaskToConstraints
установлено значение NO
.
Взаимодействие вложения представлено как сегмент класса UIStoryboardEmbedSegue
. (Это частный класс, а не открытый API).
Когда UIStoryboardEmbedSegue
получает сообщение perform
, он загружает представление контроллера представления назначения и добавляет его в качестве подсмотра представления контейнера. Затем он устанавливает встроенный вид autoresizingMask
в UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight
. Это избыточно, поскольку Interface Builder уже установил его таким образом в раскадровке.
Затем -[UIStoryboardEmbedSegue perform]
проверяет встроенный просмотр translatesAutoresizingMaskToConstraints
. Это также избыточно, потому что Interface Builder установил его в YES
.
Если встроенный просмотр translatesAutoresizingMaskToConstraints
равен YES
, perform
устанавливает встроенный вид frame
в представление контейнера bounds
. Опять же, избыточный.
Если встроенный просмотр translatesAutoresizingMaskToConstraints
равен NO
, perform
добавляет ограничения H:|[childView]|
и V:|[childView]|
, тем самым вынуждая встроенный просмотр заполнить представление контейнера. (Да, на самом деле он использует язык визуального формата.) Эта ветка не должна быть достигнута.
Если для представления translatesAutoresizingMaskToConstraints
установлено значение YES
, автоматический макет автоматически добавляет ограничения типа NSAutoresizingMaskLayoutConstraint
и сохраняет их в актуальном состоянии при изменении вида frame
. Например, корневой вид окна создается для заполнения окна с помощью ограничений автосохранения:
<NSAutoresizingMaskLayoutConstraint:0x7555d00 h=-&- v=-&- UIView:0x7671780.midX == UIWindow:0x7551010.midX>,
<NSAutoresizingMaskLayoutConstraint:0x7555de0 h=-&- v=-&- UIView:0x7671780.width == UIWindow:0x7551010.width>,
<NSAutoresizingMaskLayoutConstraint:0x7555eb0 h=-&- v=-&- UIView:0x7671780.midY == UIWindow:0x7551010.midY + 10>,
<NSAutoresizingMaskLayoutConstraint:0x7555ef0 h=-&- v=-&- UIView:0x7671780.height == UIWindow:0x7551010.height - 20>
Итак, что-то "заставляет Container View держать свой дочерний ракурс просмотра в соответствии с его границами".
Я понял это, посмотрев файл .storyboard
(это удивительно читаемый XML) и посмотрев -[UIStoryboardEmbedSegue perform]
в Hopper.
Что касается того, почему у них избыточные проверки, я могу предположить несколько возможных причин:
-
IB (возможно, в версиях до выпуска) не всегда настраивал свойства представления так, как это делает сейчас, поэтому код не избыточен при загрузке старых раскадровки.
-
У Apple есть внутренние инструменты, которые генерируют раскадровки по-разному, чем IB.
-
Код для передовой совместимости с будущими версиями IB, которые позволяют представлениям верхнего уровня раскадров иметь разные свойства.