Ответ
Нет. Методы жизненного цикла, связанные с view (viewDidLoad, viewWillAppear и т.д.), не вызываются во время инициализации контроллера через init(nibName:bundle:) или init(coder:).
Последовательность событий
- Инициализация (
init): Создается сам объектUIViewController. Его view (self.view) еще не загружена и равнаnil. - Загрузка View (ленивая): При первом обращении к свойству
view(например, из кода или при добавлении контроллера в иерархию) система запускает процесс загрузки. - Вызов методов жизненного цикла: Только после успешной загрузки 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() или позже.