Когда вызывается loadView в iOS?
Что проверяют
Знаете ли вы, что view контроллера загружается лениво и что именно запускает загрузку. Следом спрашивают, чем loadView отличается от viewDidLoad и когда его вообще стоит переопределять.
Как отвечать
loadView вызывает система, когда кто-то читает свойство view, а оно ещё nil. Не в init, а при первом обращении: обычно это делает контейнер перед показом экрана, но то же случится, если ваш код тронет vc.view раньше. Сразу после loadView вызывается viewDidLoad.
Реализация по умолчанию загружает интерфейс из nib или storyboard, если он есть, а иначе создаёт пустой UIView.
Когда переопределять:
- интерфейс кодом: создаёте корневую view и присваиваете её в
view. Типичный приём:override func loadView() { view = ProfileView() }плюс вычисляемое свойство, которое приводитviewкProfileView. Вёрстка уезжает в отдельный класс, контроллер худеет; - без
super.loadView(): в своей реализации его не вызывают, иначе система зря создаст стандартную view или полезет за nib; - только иерархия: подписки, загрузку данных и сетевые запросы оставляйте для
viewDidLoad.
Полезные соседи: isViewLoaded и viewIfLoaded проверяют состояние, ничего не загружая, а loadViewIfNeeded() загружает view принудительно, что удобно в юнит-тестах. Сам loadView вручную не вызывают.
Повторного вызова можно не ждать: начиная с iOS 6 система не выгружает view при нехватке памяти. Метод сработает снова, только если вы сами обнулите view.
Где спотыкаются
Переопределяют loadView у контроллера из storyboard. Интерфейс из сториборда перестаёт загружаться, аутлеты остаются nil.
Трогают view слишком рано, например задают vc.view.backgroundColor в инициализаторе или до перехода. loadView и viewDidLoad отрабатывают прямо в этот момент, когда зависимости ещё не переданы.
Считают размеры в loadView или viewDidLoad. Финальных bounds там ещё нет, геометрию правильнее считать в viewDidLayoutSubviews или viewIsAppearing.