Сколько раз вызывается метод `viewDidLoad` у UIViewController?

Ответ

Метод viewDidLoad() вызывается один раз за жизненный цикл контроллера, при первой загрузке его view в память.

Ключевые моменты:

  • Вызов происходит, когда система впервые запрашивает свойство view контроллера, и оно равно nil.
  • После вызова viewDidLoad() view контроллера создана и загружена, но еще не отображена на экране.
  • Повторный вызов возможен только если view была выгружена из памяти (например, при сильном недостатке памяти и вызове didReceiveMemoryWarning, или если контроллер не находится в иерархии навигации), а затем потребовалась снова.

Отличие от других методов жизненного цикла:

class ExampleViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Идеальное место для первоначальной настройки UI.
        // Вызывается ОДИН РАЗ.
        setupInitialView()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // Вызывается КАЖДЫЙ РАЗ перед появлением view на экране.
        // Место для обновления данных, анимаций.
        refreshData()
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // Вызывается после того, как view скрылась с экрана.
    }
}

Практический совет: Не помещайте в viewDidLoad код, который должен выполняться при каждом появлении экрана (например, загрузку актуальных данных). Для этого используйте viewWillAppear или viewDidAppear.

Ответ 18+ 🔞

Давай разжую про этот самый viewDidLoad, чтобы понятно стало, как он работает, а то народ путает его с другими методами и потом удивляется, почему хуйня не работает.

Представь себе, что твой контроллер — это новый смартфон, который ты только что распаковал. Метод viewDidLoad() — это тот самый момент, когда ты его впервые включаешь, видишь приветственный экран и начинаешь настраивать: язык, Wi-Fi, скачиваешь приложения. Один раз, сука! Пока ты его не выключишь и не выбросишь нахуй (то есть view не выгрузится из памяти из-за нехватки оной), второй раз этот экран приветствия ты не увидишь.

Ключевые моменты, чтобы не быть мудаком:

  • Система дергает этот метод, когда впервые пытается достучаться до свойства view контроллера, а там пусто, nil. Она такая: «А view-то где? Надо создать!» Создает, загружает и говорит: «Опа, viewDidLoad, делай что хочешь».
  • В этот момент вьюха уже есть в памяти, собрана из ксиба или сториборда, но на экране ее еще нет. Она как бы за кулисами стоит.
  • Повторный вызов — это как воскрешение. Возможен только в одном пиздецовом сценарии: система в крике «ПАМЯТИ НЕТ!» выгрузила твою вьюху (вызвав didReceiveMemoryWarning), а потом тебе снова понадобилось на этот экран перейти. Тогда она загрузится заново и viewDidLoad вызовется снова. Но это нечастое явление, рассчитывать на него не стоит.

Чем он не является, блядь? Он не вызывается каждый раз, когда ты возвращаешься на экран. Для этого есть другие ребята.

Смотри, вот тебе пример, чтобы в голове уложилось:

class ExampleViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Идеальное место для разовой, тяжелой настройки.
        // Типа добавить сабвью, настроить статические данные.
        // Вызывается ОДИН РАЗ за сессию жизни вьюхи.
        setupInitialView() // Сделал и забыл.
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // А вот это вызывается КАЖДЫЙ РАЗ, когда экран вот-вот появится.
        // Тут обновляешь данные, которые могли устареть.
        // Или запускаешь анимацию.
        refreshData() // Делается при каждом входе.
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // Вызывается, когда вьюха уже скрылась.
        // Тут можно аудио остановить или анимации прибрать.
    }
}

Практический совет, чтобы не облажаться: Не пихай в viewDidLoad то, что должно происходить при каждом показе экрана. Например, запрос к апи за свежими новостями или обновление прогресса. Положишь это в viewDidLoad — и будешь потом чесать репу, почему данные старые, когда вернулся с другого экрана. Для такой динамики нужны viewWillAppear или viewDidAppear. viewDidLoad — для фундамента, который закладывается один раз и на долго.