Как правильно обновлять frame или layout в iOS после того, как размеры стали известны?

«Как правильно обновлять frame или layout в iOS после того, как размеры стали известны?» — вопрос из категории UIKit, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для обновления макета после расчета системных размеров используйте следующие методы:

Для 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 возможно, но не рекомендуется, так как система может перезаписать ваши изменения своим итоговым расчетом.