Вызываются ли методы жизненного цикла UIViewController при его инициализации (init)?

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

Ответ

Нет. Методы жизненного цикла, связанные с view (viewDidLoad, viewWillAppear и т.д.), не вызываются во время инициализации контроллера через init(nibName:bundle:) или init(coder:).

Последовательность событий

  1. Инициализация (init): Создается сам объект UIViewController. Его view (self.view) еще не загружена и равна nil.
  2. Загрузка View (ленивая): При первом обращении к свойству view (например, из кода или при добавлении контроллера в иерархию) система запускает процесс загрузки.
  3. Вызов методов жизненного цикла: Только после успешной загрузки view вызываются соответствующие методы.

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

class DemoViewController: UIViewController {
    // 1. Инициализация
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        print("1. init called. View is nil? (self.view == nil)") // true
    }

    // 2. Загрузка View (системный вызов)
    override func loadView() {
        print("2. loadView called")
        view = UIView() // Создаем view вручную
    }

    // 3. View загружена и готова
    override func viewDidLoad() {
        super.viewDidLoad()
        print("3. viewDidLoad called. View is nil? (self.view == nil)") // false
        // Здесь безопасно настраивать элементы интерфейса.
    }

    // 4. View появится на экране
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("4. viewWillAppear called")
    }
}
// Использование:
let vc = DemoViewController(nibName: nil, bundle: nil) // Выведет только "1. init..."
// vc.view // Раскомментировать для принудительной загрузки view и вызова 2, 3.

Важное следствие: Не пытайтесь обращаться к self.view или outlet-ам внутри init. Они будут nil. Вся настройка, зависящая от view, должна выполняться в viewDidLoad() или позже.