В каком методе жизненного цикла UIViewController можно получить корректные данные о frame экрана?

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

Ответ

viewDidLayoutSubviews() — это наиболее подходящий метод для получения окончательных размеров и позиций view.

Почему? Этот метод вызывается после того, как система завершила расчет layout для контроллера и всех его subviews. Значения frame и bounds здесь гарантированно актуальны.

Пример:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Теперь frame корневой view корректен
    print("Main view frame: (view.frame)")
    // Можно безопасно позиционировать subviews
    customSubview.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 100)
}

Важные нюансы:

  • viewDidLoad()не подходит, так как view загружена в память, но её geometry (размеры и положение) ещё не рассчитана относительно родительского контекста (окна, safe area).
  • viewWillAppear(_:) — тоже может давать некорректные значения, так как final layout ещё не выполнен.
  • viewDidAppear(_:) — даст правильные значения, но вызывается позже, после появления view на экране, что может быть слишком поздно для начальной настройки UI.
  • Метод viewDidLayoutSubviews() может вызываться несколько раз (поворот, изменение constraints, вызов setNeedsLayout()). Для однократной настройки используйте флаг:
    private var isFirstLayout = true
    override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if isFirstLayout {
        isFirstLayout = false
        // Настройка, выполняемая один раз
    }
    }