Жизненный цикл UIViewController
Краткая справка от автора перевода:
UIViewController (ViewController) - Это класс унаследованный от стандартного UIViewController, который является базовым контроллером паттерна MVC, который Apple рекомендует использовать для разработки iOS приложений. Сущность UIViewController’a используется для контроля UIView
UIView (View/ Вью) – Представляет собой экран или значительную часть экрана.
SubView - это базовый класс для виджетов, который используется для создания интерактивных компонентов пользовательского интерфейса (кнопки, текстовые поля и т.д.). и если мы вставим view внутри другого view, то он станет Subview.
Storyboards(сториборды) – это функция Xcode для облегченной разработки интерфейсов приложений. Выглядит как раскадровка экранов приложения.
Nib-файл - это описание фрагмента пользовательского интерфейса в скомпилированном формате в файле с расширением . nib.
IBOutlet в основном, — это связь элемента UI (кнопки или лейбла) с его ссылкой в коде.
IBAction — это действие (или метод, как удобнее) в коде, которое можно подключить к некоторому событию (нажатие кнопки, например) в разработанном интерфейсе.
Bounds - местоположение и размер представления с использованием его собственной системы координат (важно для размещения содержимого View или subview внутри него)
Frames - расположение и размер view с использованием системы координат родительского представления (важно для размещения представления в superview).
init(coder:)
· Когда вызывается / Когда используется:
View Controller обычно создается из сторибордов. В этом случае вызывается инициализатор init(coder:), который необходимо переопределить.
Он предоставляет экземпляр NSCoder в качестве параметра, который вам нужен, только если вы используете API-интерфейсы сериализации iOS. Это используется не часто, поэтому вы можете игнорировать этот параметр. Эта сериализация преобразует объект в поток байтов, который вы можете сохранить на диске или отправить по сети.
· Применение :
На этапе инициализации ViewController'a вы обычно выделяете ресурсы, которые потребуются ViewController'у в течение его жизненного цикла. К ним относятся объекты модели или другие вспомогательные контроллеры, такие как сетевые контроллеры.
Предыдущие контроллеры также могут передавать эти объекты текущему, поэтому вам не всегда нужно создавать их экземпляры в каждом контроллере.
· О чем нужно позаботиться:
Имейте в виду, что на данный момент вью ViewController’a еще не создано. Если вы попытаетесь получить к нему доступ через вью свойства ViewController’a, будет вызван метод loadView(). Это может привести к неожиданному поведению и ошибкам, поэтому безопаснее обращаться к вью на более позднем этапе жизненного цикла.
init(nibName:bundle:)
· Когда вызывается / Когда используется:
Иногда вы можете решить поместить интерфейс вашего ViewController’a в отдельный nib-файл вместо сториборда. Например, при работе в большой команде, где разные разработчики должны изменять интерфейсы ViewController’a, не влияя на работу друг-друга. У вас также может быть проект, который был создан, когда сторибордов еще не существовало, поэтому у каждого ViewController’a был свой собственный nib-файл. Обратите внимание, что, если ваш Main(Основной) Storyboard становится слишком большой, вы можете разделить его на несколько Storyboard’ов. Вам не нужно перемещать каждый ViewController в отдельный nib-файл.
Если вы создаете ViewController из nib-файла, этот инициализатор вызывается вместо init(coder:).
loadView()
Это метод, который создает view для ViewController’a. Вы переопределяете этот метод только в том случае, если хотите построить весь интерфейс для ViewController’a из кода. Не используйте его, если нет уважительной причины.
Если вы работаете со Stryboard'ми или nib-файлами, вам не нужно ничего делать с этим методом, и вы можете его игнорировать. Его реализация в UIVIewController загружает интерфейс из файла и подключает за вас все Outlets и Actions.
viewDidLoad()
Когда этот метод вызывается, вью ViewController’a создано, и вы можете быть уверены, что все Outlets на месте.
· Применение:
Обычно этот метод используется для заполнения пользовательского интерфейса ViewController’a данными до того, как пользователь их увидит.
Это также хорошее место для начала какой-либо фоновой деятельности, в конце которой вам нужно иметь готовый пользовательский интерфейс.
Распространенным случаем являются сетевые вызовы, которые нужно сделать только один раз при загрузке экрана.
Хорошее место для инициализации и настройки объектов, используемых в viewController.
· viewDidLoad V/S viewDidAppear :
Если вам нужно повторить их (фоновая активность/изменения пользовательского интерфейса/выполнение сетевых вызовов) для обновления данных ViewController'a, viewDidAppear(_:) более подходит для этого.
· Важно помнить:
Этот метод вызывается только один раз за время жизни ViewController'a, поэтому вы используете его для вещей, которые должны произойти только один раз. Если вам нужно выполнять какую-то задачу каждый раз, когда на экране появляется ViewController, вам понадобятся следующие методы.
Следует учесть, что на данном этапе жизненного цикла вью bounds(границы) не являются окончательными.
viewWillAppear(_:)
Вы переопределяете этот метод для задач, которые вам нужно повторять каждый раз, когда ViewController появляется на экране. Этот метод можно вызывать несколько раз для одного и того же экземпляра ViewController'a.
Уведомляет ViewController о том, что его view будет добавлено в иерархию отображения (view hierarchy).
· Применение:
Обычно этот метод используется для обновления пользовательского интерфейса данными, которые могли измениться, пока ViewController не отображался на экране.
Вы также можете подготовить интерфейс для анимаций, которые вы хотите запускать при появлении ViewController'a.
· viewDidLoad V/S viewDidAppear :
Код, который вам нужно выполнить только один раз, должен войти в инициализатор или viewDidLoad().
На этом этапе границы вида определены, но ориентация не применяется.
viewWillLayoutSubViews:
Вызывается, чтобы уведомить ViewController о том, что его view собирается разместить свои subviews.
Этот метод вызывается каждый раз, когда frame изменяется, например, при повороте экрана или, когда он помечен как needing layout(требующий компоновки). Это первый шаг, на котором bounds(границы) view являются окончательными.
Если вы не используете autoresizingMask или constraints, а размер view изменяется, вы, вероятно, захотите обновить subviews здесь.
viewDidLayoutSubviews:
Вызывается, чтобы уведомить ViewController о том, что его view только что разместило свои subview.
Внесите дополнительные изменения здесь после того, как view разместит свои subview.
viewDidAppear(_:)
Этот метод вызывается после того, как ViewController появляется на экране.
Вы можете использовать его для запуска анимации в пользовательском интерфейсе, для воспроизведения видео или звука или для начала сбора данных из сети.
viewWillDisappear(_:)
Этот метод вызывается до того, как произойдет переход к следующему View Controller’у и исходный ViewController будет удален с экрана.
Вам редко нужно переопределять этот метод, так как на этом этапе необходимо выполнить несколько общих задач, но он может вам понадобиться.
viewDidDisappear(_:)
После удаления ViewController'a с экрана вызывается этот метод.
Обычно вы переопределяете этот метод, чтобы остановить задачи, которые не должны выполняться, пока ViewController не отображается на экране.
Например, вы можете перестать получать уведомления, наблюдать за свойствами других объектов, отслеживать датчики устройства или сетевой вызов, который больше не нужен.
deinit()
Как и любой другой объект, прежде чем ViewController будет удален из памяти, он деинициализируется.
· Применение :
Обычно вы переопределяете deinit() для очистки ресурсов, выделенных ViewController, которые не освобождаются ARC (автоматический подсчет ссылок).
Вы также можете остановить задачи, которые вы не остановили в предыдущем методе, потому что вы хотели оставить их в фоновом режиме.
· Следует опасаться :
ViewController исчезает с экрана, но это не означает, что впоследствии он будет освобожден. Многие контейнеры хранят viewController в памяти. Например, когда вы углубляетесь в navigation controller, все предыдущие viewController остаются в памяти. Navigation controller освобождает viewController'ы только при переходе вверх по иерархии. Поэтому вы должны иметь в виду, что viewController, который не находится на экране, все равно работает нормально и получает уведомления. Иногда это желательно, иногда нет, поэтому вам нужно помнить об этом при разработке приложения.
didReceiveMemoryWarning()
Устройства iOS имеют ограниченный объем памяти и мощности. Когда оперативная память начинает заполняться, iOS не использует дополнительно память на жестком диске для перемещения данных, как это делает компьютер. По этой причине вы несете ответственность за то, сколько ваше приложение занимает оперативной памяти. Если ваше приложение начнет использовать слишком много памяти, iOS уведомит об этом.
Поскольку viewController'ы выполняют управление ресурсами, эти уведомления доставляются им с помощью этого метода. Таким образом, вы можете предпринять действия, чтобы освободить часть памяти. Имейте в виду, что если вы проигнорируете предупреждения о нехватки памяти и память, используемая вашим приложением, превысит определенный порог, iOS завершит работу вашего приложения. Это будет выглядеть как краш для пользователя, и его следует избегать.