Вызывается ли viewDidLoad в iOS один раз или несколько раз?
Что проверяют
Понимаете ли вы жизненный цикл UIViewController и разницу между загрузкой представления и его появлением на экране. Следом спрашивают, куда класть код, который должен выполняться при каждом показе экрана, и почему в viewDidLoad нельзя верить размерам.
Как отвечать
Короткий ответ: один раз на экземпляр контроллера. Дальше объясните, почему и какие есть оговорки:
- когда вызывается: после того как представление загружено в память, то есть после
loadViewили загрузки из storyboard и xib. Загрузка ленивая, её запускает первое обращение к свойствуview; - почему один раз: начиная с iOS 6 система не выгружает представления при нехватке памяти, а
viewDidUnloadустарел. Пока жив экземпляр, егоviewзагружен, и повторного вызова нет; - когда «вызывается снова»: если создан новый экземпляр. Экран, закрытый через
popи открытый заново, обычно новый объект. Второй вызов на том же экземпляре возможен, только если вручную обнулитьviewи снова к нему обратиться; - что туда класть: разовую настройку. Создание сабвью, констрейнты, подписки, первичный запрос данных;
- что туда не класть: код, завязанный на показ или геометрию. Для каждого появления есть
viewWillAppearиviewDidAppear, для размеровviewDidLayoutSubviews. В iOS 17 появилсяviewIsAppearing, доступный и на более старых версиях: в нём уже известны трейты и размеры, но экран ещё не показан.
Если проект на SwiftUI, оговоритесь: прямого аналога там нет, а onAppear и .task срабатывают при каждом появлении экрана, поэтому разовую загрузку держат во вью-модели с флагом «уже загружено».
Где спотыкаются
Повторяют старый тезис, что при предупреждении о памяти представление выгружается и viewDidLoad вызовется снова. Так было до iOS 6.
Обращаются к vc.view сразу после создания контроллера, например чтобы задать цвет фона. Это запускает загрузку раньше времени, и viewDidLoad отрабатывает до того, как в контроллер переданы данные.
Рассчитывают фреймы в viewDidLoad по view.bounds. Там ещё размеры из storyboard, а не реального устройства, и вёрстка съезжает на другом экране.