Жизненный цикл UIViewController

Большинство приложения под iOS пишутся с использованием UIKit, а значит, используют UIViewController. Они настолько же просты, насколько и сложны. Основная масса сложностей возникает из-за непонимания что, когда, как и зачем происходит внутри стандартных методов UIViewController.
Сразу определимся, разговор пойдет только о самых важных события жизненного цикла. Мы не будем касаться вопросов смены ориентации устройства, обработки событий клавиатуры, прерываний процесса работы и прочего.

Отдельно, стоит хорошо понимать, что на UIViewController «возложена» обязанность контроля не только над своим жизненым циклом, но и над циклом жизни собственного UIView.

Начнем с начала.
Создание UIViewController
init
initWithNibName:

Уничтожение UIViewController
dealloc

Создание UIView
isViewLoaded
loadView
viewDidLoad
initWith****

Обработка изменения состояния UIView
viewDidLoad
viewWillAppear
viewDidAppear
viewWillDisappear
viewDidDisappear
viewDidUnload

Уничтожение UIView
viewDidUnload

Обработка нехватки памяти
didReceiveMemoryWarning

«Жизнь» начинается.
Независимо от того, как именно инциализируется контроллер (UIViewController) (с подключение *.NIB файла или нормально), происходит вызов метода init, в котором и появляется значение переменной self, вернее, ее значение перестает быть nil и заменяется указателем на конкретный блок памяти.
ВАЖНО! Инициализируется только сам контроллер. Никакого вида (UIView) не существует (хотя он и инициализирован, т.е. обращение к self.view возможно). Если вы использует NIB-ы — никаких оутлетов на этом этапе еще нет. Соответственно — попытка создания или обращения к визуальным компонентам приведет к ошибке.
СТОИТ ПОМНИТЬ! В любой момент можно проверить, загружен вид в память или нет (а соответственно, можно ли обращаться к визуальным элементам) с помощью метода isViewLoaded. Главная его особенность в том, что он не «провоцирует» загрузку вида, если еще не загружен.

Создание вида (UIView).
В самом общем случае, создание вида (его загрузка в память) начинается в тот момент, когда произойдет любое обращение к self.view. Будет вызван метод loadView, результатом которого будет или созданный пустой вид, либо вид с элементами из NIB-а. Именно в этот момент наш котроллер и его вид становятся полностью доступными.
По оканчании загрузки будет вызван метод viewDidLoad
ВАЖНО! Загрузка вида, это именно загрузка, т.е. размещение всего необходимого для отображения вида в памяти. Не более того. Все загрузили и подготовили. Ждем команды «показать».
СТОИТ ПОМНИТЬ! Если вы интерфейс создаете нормально, т.е. с использованием кода, то собственные элементы интерфейса вы можете создавать/добавлять на вид/настраивать как в методе loadView, так и в метода viewDidLoad.
Если вы используете NIB-ы, то для настройки элементов интерфейса вам доступен только метод viewDidLoad.

Жизнь вида.
viewDidLoad — вид загружен и полностью готов к работе. Многим нравится именно в этом методе делать, т.с. «вторую часть инициализации контроллера». Привычка — вторая натура.
viewWillAppear — будет вызван перед тем, как начать отображение вида. В случае, если для отображения используется анимация — перед началом анимации.
viewDidAppear — будет вызван после окончания отображение вида. В случае, если для отображения используется анимация — после окончания анимации отображения.

viewWillDisappear — тоже, что и viewWillAppear, только когда вид прекращает отбражение.
viewDidDisappear — тоже, что и viewDidAppear, только когда вид прекращает отбражение.

viewDidUnload — вид выгружен из памяти
ВАЖНО! Выгружен сам вид, но не элементы интерфейса, которые мы создавали. Именно в этом методе их нужно уничтожить. Если вы используете NIB-ы — пришла пора очистить все оутлеты. Если вы этого не сделаете, система за вас это делать не будет.

Конец жизненного пути контроллера.
Когда вы уничтожите контроллер (указатель на него сбросите в nil) ARC очистит выделенную для него память. Перед этим будет вызван метод dealloc. Именно в нем нобходимо выполнить очистку и обнуление всех указтелей, которые вы создали для использования внутри контроллера.
ВАЖНО! Если вид контроллера еще отображается, а вы обнулите указатель на сам контроллер, то dealloc — будет вызван, а viewDidUnload — нет, вернее, скорее всего, что нет.

Обработка нехватки памяти
Метод didReceiveMemoryWarning вызывается системой, при нехватке памяти.
По умолчанию, реализация этого метода для контроллера, который не находится в видимой области, вызывает освобождение и удаление вида, что, в свою очередь, приведет к вызову viewDidUnload.
В любом случае — если система «потребовала» (этот метод — это именно требование) вам необходимо его исполнить как можно эффективней.
СТОИТ ПОМНИТЬ! Бог любит троицу. Система дажды потребует освобождения памяти (если вы не поняли с первого раза). Третий раз требование придет вместе с остановкой программы по критической ошибке. Все очень просто и надежно.

На последок…
Этот текст не является полной пошаговой инструкцией. Я коснулся только некоторых важных азов. Дерзайте и познавайте.
ВАЖНО! Работая с памятью, помните — сам взял, сам — вернул.

Добавить комментарий


+ семь = восемь

Ваш e-mail не будет доступен другим пользователям. Все поля обязательны для заполнения.