Какие способы загрузки view существуют в iOS
Что проверяют
Понимаете ли вы жизненный цикл view у UIViewController: когда она создаётся, откуда берётся и что можно переопределить. Следом обычно спрашивают разницу loadView() и viewDidLoad() и почему IBOutlet оказался nil.
Как отвечать
Ключевая мысль: view у контроллера ленивая. При первом обращении UIKit вызывает loadView(), затем viewDidLoad(). Стандартная loadView() берёт интерфейс из связанного nib: из storyboard, из которого создан контроллер, из файла, указанного в init(nibName:bundle:), или из nib с именем класса. Если ничего нет, создаётся пустой UIView. Отсюда способы:
- storyboard:
instantiateViewController(withIdentifier:). С iOS 13 естьinstantiateViewController(identifier:creator:), он позволяет передать зависимости через свой инициализатор; - XIB для контроллера:
init(nibName:bundle:), файл подгружается при первом обращении кview; - XIB для отдельной вью:
UINib(nibName:bundle:).instantiate(withOwner:options:)илиBundle.main.loadNibNamed(_:owner:options:), после загрузки вызываетсяawakeFromNib(); - код: переопределённый
loadView()с присваиваниемview = ProfileView()без вызоваsuper. Настройку и привязку данных делают вviewDidLoad(); - ячейки:
register(_:forCellReuseIdentifier:)с классом илиUINib, затемdequeueReusableCell. Это и есть встроенное переиспользование вью, отдельного «кэша вью» нет; - SwiftUI: встраивается в UIKit через
UIHostingController, а UIKit-вью в SwiftUI черезUIViewRepresentable.
Для своей UIView помните про два инициализатора: init(frame:) при создании в коде и init?(coder:) при загрузке из Interface Builder.
Где спотыкаются
Вызывают super.loadView() и затем подменяют view. Документация прямо просит не вызывать super в своей реализации, иначе работа делается дважды.
Контроллер, свёрстанный в storyboard, создают через MyViewController(). Интерфейс не подгружается, все IBOutlet равны nil, приложение падает на первом обращении.
Рассчитывают фреймы в viewDidLoad(). Размеры там ещё не финальные, геометрию правильно считать в viewDidLayoutSubviews() или отдать Auto Layout.