← Назад к вопросам

Вызывается ли жизненный цикл ViewController при его инициализации?

1.0 Junior🔥 261 комментариев
#UIKit и верстка

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Жизненный цикл ViewController при инициализации

Ответ: НЕТ, lifecycle методы не вызываются при инициализации

Это частая ошибка в понимании архитектуры iOS. При создании экземпляра ViewController вызывается только инициализатор (init), но lifecycle методы НЕ вызываются.

Фазы загрузки ViewController

1. Инициализация (Initialization)

// Фаза 1: init вызывается сразу
class MyViewController: UIViewController {
    init() {
        super.init(nibName: nil, bundle: nil)
        // Инициализация свойств
        print("1. init() — объект создан в памяти")
        // Но lifecycle методы ещё НЕ вызваны!
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        print("1. init(coder:) — из Storyboard")
    }
}

// ViewController создан, но не загружен
let controller = MyViewController()
// Вывод: "1. init() — объект создан в памяти"
// Больше ничего не вызывается!

2. Загрузка View (View Loading)

Lifecycle методы начинают вызываться только когда view физически загружается:

class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        print("3. viewDidLoad() — view загружена, иерархия создана")
        // Сейчас можно работать с UI элементами
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("4. viewWillAppear() — view вот-вот появится")
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("5. viewDidAppear() — view видна пользователю")
    }
}

// Создание controller НЕ вызывает эти методы!
let controller = MyViewController()
print("init завершен, но viewDidLoad ещё не вызван")

Полный порядок событий

let controller = MyViewController()
// Вывод:
// "1. init() — объект создан в памяти"

// Контроллер добавляется в view hierarchy
window.rootViewController = controller
// Вывод:
// "2. loadView() или view из XIB/Storyboard"
// "3. viewDidLoad() — view загружена"
// "4. viewWillAppear() — view вот-вот появится"
// "5. viewDidAppear() — view видна пользователю"

// Пользователь ушел с экрана
// Вывод:
// "6. viewWillDisappear() — view вот-вот исчезнет"
// "7. viewDidDisappear() — view больше не видна"

// При полной выгрузке
// Вывод:
// "8. deinit() — память освобождена"

Диаграмма события

┌─────────────────────────────────────┐
│  let controller = MyViewController() │
│  ✅ init() вызывается               │
│  ❌ viewDidLoad() НЕ вызывается    │
└─────────────────────────────────────┘
                 ↓
┌─────────────────────────────────────┐
│  window.rootViewController = ctl     │
│  ✅ loadView() вызывается           │
│  ✅ viewDidLoad() вызывается        │
└─────────────────────────────────────┘
                 ↓
┌─────────────────────────────────────┐
│  Переход на экран                   │
│  ✅ viewWillAppear() вызывается     │
│  ✅ viewDidAppear() вызывается      │
└─────────────────────────────────────┘
                 ↓
┌─────────────────────────────────────┐
│  Переход со экрана                  │
│  ✅ viewWillDisappear() вызывается  │
│  ✅ viewDidDisappear() вызывается   │
└─────────────────────────────────────┘

Практический пример — частая ошибка

class ProfileViewController: UIViewController {
    var user: User?
    
    init(userID: String) {
        super.init(nibName: nil, bundle: nil)
        // ❌ ОШИБКА: Пытаемся обновить UI в init
        // self.navigationItem.title = "Profile"
        // Fatal error: view property of ProfileViewController is accessed
        // before it is fully initialized
        
        // ✅ Правильно: просто сохраняем данные
        self.user = User(id: userID)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // ✅ Теперь можно работать с view
        self.navigationItem.title = user?.name ?? "Profile"
        setupUI()
    }
    
    private func setupUI() {
        // Конфигурация UI
    }
}

Что вызывается в init

class MyViewController: UIViewController {
    init() {
        super.init(nibName: nil, bundle: nil)
        
        // ✅ Допустимо: инициализация переменных
        let config = AppConfig()
        let viewModel = ViewModel()
        
        // ✅ Допустимо: сохранение параметров
        self.viewModel = viewModel
        
        // ✅ Допустимо: конфигурация сервисов
        self.analytics.setScreen("ProfileVC")
        
        // ❌ Недопустимо: обращение к view
        // self.label.text = "Hello"
        
        // ❌ Недопустимо: обращение к подвьюхам
        // self.view.addSubview(myView)
    }
}

Когда вызывать loadView

class CustomViewController: UIViewController {
    override func loadView() {
        // ✅ loadView() вызывается ДО viewDidLoad()
        // Здесь можно программно создать view
        
        let rootView = UIView()
        rootView.backgroundColor = .white
        
        let label = UILabel()
        label.text = "Hello"
        rootView.addSubview(label)
        
        self.view = rootView
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Сейчас self.view определён и готов к использованию
    }
}

Summary: Порядок вызовов

СобытиеinitloadViewviewDidLoadviewWillAppearviewDidAppear
Controller создан
View добавлена в иерархию
Переход на экран

Важные выводы

  1. init НЕ гарантирует жизненный цикл — используй инициализатор только для инициализации data
  2. viewDidLoad — точка старта — здесь можно безопасно работать с UI
  3. loadView — программное создание view — переопредели только если нужна кастомная иерархия
  4. viewWillAppear/viewDidAppear — видимость — используй для обновления данных и отписки от событий
  5. Тестируй с print() — добавь логирование во все методы жизненного цикла для понимания
Вызывается ли жизненный цикл ViewController при его инициализации? | PrepBro