Жизненный цикл UIViewController включает ключевые методы:
init(nibName:bundle:) / init(coder:): инициализацияloadView: создание иерархии viewviewDidLoad: view загружена (идеальное место для первоначальной настройки)viewWillAppear / viewDidAppear: view показывает/показанаviewWillDisappear / viewDidDisappear: view скрывается/скрытаdeinit: удаление контроллераПорядок вызова методов:
loadView, затем viewDidLoad)viewWillAppear/viewWillDisappear, затем viewDidAppear/viewDidDisappeardeinitТонкости:
viewDidLoad не стоит обращаться к размерам view — они могут быть неактуальныdeinit или viewWillDisappearviewDidLoad, но не в viewWillAppear — иначе возможно дублирование при каждом появленииПример:
class MyViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setupViews() setupBindings() } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // Subscribe to notifications } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Unsubscribe from notifications } deinit { // Clean up } }
Вопрос:
Допускается ли вью-контроллеру обращаться к свойствам view вне жизненного цикла (например, в инициализаторе)?
Ответ:
Нет, до момента вызова (или переопределения) loadView все свойства, связанные с view, могут быть неинициализированы. Любой доступ к ним вне loadView/viewDidLoad приведёт к крэшу.
Пример:
// Ошибка: self.view ещё не инициализирована! init() { super.init(nibName: nil, bundle: nil) self.view.backgroundColor = .red //КРАШ }
История
Проект падал из-за преждевременного обращения к self.view в init — view не была создана, приводило к крэшу.
История
В крупных проектах забывали отписаться от NotificationCenter или delegate в viewWillDisappear и/или deinit, что приводило к утечкам памяти (NotificationCenter ссылался на view controller, он не освобождался и продолжал слушать события).
История
В viewWillAppear каждое появление добавлялись новые сабьюхи к view (например, показывали индикатор загрузки), не проверяя существование. В результате при каждом возврате на экран появлялось всё больше дублирующихся индикаторов, UI выходил из строя.