Ответ
Корневое view (свойство view) создаётся лениво, в момент первого к нему обращения. Система управляет этим процессом через механизм Lifecycle Load.
Процесс загрузки view:
- При первом обращении к свойству
view(например, в коде или при добавлении контроллера в иерархию), если оноnil, вызывается методloadView(). - Метод
loadView():- Ответственен за создание и присвоение корневого
viewсвойствуview. - По умолчанию он создаёт пустое
UIView, еслиnibNameне указан. - Переопределять его нужно осторожно, только для создания view программно, не вызывая
super.loadView()(если создаёте view вручную).
- Ответственен за создание и присвоение корневого
- Сразу после
loadView()вызываетсяviewDidLoad()— здесьviewгарантированно загружена и готова для начальной настройки.
Практические следствия и примеры:
-
Опасный код (краш): Обращение к
viewдо её загрузки, например, в инициализаторе.class MyVC: UIViewController { init() { super.init(nibName: nil, bundle: nil) view.backgroundColor = .red // CRASH! `view` is nil. } } -
Безопасный код: Вся работа с иерархией view должна быть в
viewDidLoad()или позже.class MyVC: UIViewController { override func viewDidLoad() { super.viewDidLoad() // `view` здесь уже создана и безопасна для использования. view.backgroundColor = .white setupSubviews() } } -
Принудительная загрузка: Если необходимо получить доступ к
viewдо её показа (редкий кейс), можно использоватьloadViewIfNeeded()(iOS 9+).let vc = MyVC() vc.loadViewIfNeeded() // View создана, viewDidLoad вызван. print(vc.view.frame) // Безопасно.