Ответ
Для обновления макета после расчета системных размеров используйте следующие методы:
Для UIViewController:
Переопределите viewDidLayoutSubviews(). На этом этапе геометрия view-контроллера и его корневого view уже установлена системой.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Безопасно изменяйте frame или обновляйте constraints
headerView.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 100)
}
Для кастомного UIView:
Переопределите layoutSubviews(). Этот метод вызывается, когда система запрашивает у view расчет расположения его subviews.
override func layoutSubviews() {
super.layoutSubviews()
// Установите frame subviews относительно текущих bounds
iconView.frame = bounds.insetBy(dx: 10, dy: 10)
}
Ключевые правила:
- Не вызывайте
setNeedsLayout()илиlayoutIfNeeded()внутриviewDidLayoutSubviewsилиlayoutSubviews, чтобы избежать бесконечного цикла. - Избегайте сложной логики. Эти методы могут вызываться часто.
- Для сложных интерфейсов предпочтительнее Auto Layout. Устанавливайте или активируйте constraints в
viewDidLoad()илиupdateViewConstraints(), а система автоматически рассчитает frame в цикле layout. - Изменение frame внутри
viewWillLayoutSubviewsвозможно, но не рекомендуется, так как система может перезаписать ваши изменения своим итоговым расчетом.