Ответ
Для позиционирования subviews на основе реальных размеров родительской view используйте viewDidLayoutSubviews().
Почему? В этом методе система уже применила все constraints, рассчитала frames с учётом safe area, размеров экрана и ориентации. Любые вычисления geometry здесь будут точными.
Пример настройки subview:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Безопасно используем bounds корневой view
let safeBounds = view.bounds.inset(by: view.safeAreaInsets)
headerView.frame = CGRect(
x: 0,
y: safeBounds.origin.y,
width: safeBounds.width,
height: 44
)
// Или ручная настройка autolayout constraints
customConstraint.constant = safeBounds.width * 0.8
}
Критические правила:
- Не вызывайте
layoutIfNeeded()внутриviewDidLayoutSubviews()— это может привести к рекурсивному циклу layout. - Метод вызывается многократно. Используйте флаги для одноразовой инициализации.
- Для динамической адаптивной вёрстки предпочтительнее использовать Auto Layout constraints. Ручной расчет frame в
viewDidLayoutSubviews— это "запасной" вариант для сложных или производительных сценариев.
Альтернатива для Auto Layout: Переопределите updateViewConstraints() для динамического обновления constraints в ответ на изменение размеров.