Добавлена ли корневая view контроллера в иерархию окон к моменту вызова viewWillAppear(_:)?

«Добавлена ли корневая view контроллера в иерархию окон к моменту вызова viewWillAppear(_:)?» — вопрос из категории UIKit, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, добавлена. К моменту вызова viewWillAppear(_:) корневая view контроллера уже является частью иерархии окон (window и superview назначены). Однако она еще не отрисована на экране.

Последовательность событий при показе UIViewController:

  1. loadView() / viewDidLoad() — создание и первичная настройка view.
  2. Добавление view в иерархию окон (например, при present или push).
  3. viewWillAppear(_:)view уже в иерархии, но невидима. Идеальное место для синхронизации UI с актуальными данными, запуска подготовительных анимаций или обновления навигационного бара.
  4. viewWillLayoutSubviews() / viewDidLayoutSubviews() — расчет лейаута (могут вызываться и раньше).
  5. Отрисовка view на экране.
  6. viewDidAppear(_:) — view полностью видима и отрисована.

Практический пример:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // View уже в иерархии, можно безопасно обращаться к superview
    print(view.superview != nil) // true
    print(view.window != nil) // true

    // Обновляем UI, который мог измениться на другом экране
    tableView.reloadData()
    // Скрываем/показываем элементы навигации
    navigationController?.setNavigationBarHidden(true, animated: animated)
    // Запускаем анимацию появления
    startInitialAlphaAnimation()
}

Важно: Поскольку viewWillAppear может вызываться многократно (например, при возврате из модального экрана), код в нем должен быть идемпотентным или корректно обрабатывать повторные вызовы.