Хотите понять жизненный цикл iOS UIViewController

299

Не могли бы вы объяснить мне, как правильно управлять UIViewControllerжизненным циклом?

В частности, я хотел бы знать , как использовать Initialize, ViewDidLoad, ViewWillAppear, ViewDidAppear, ViewWillDisappear, ViewDidDisappear, ViewDidUnloadи Disposeметоды в Mono Touch , для UIViewControllerкласса.

Лоренцо Б
источник
Есть ли какая-то информация или ссылка для OSX ViewController и WindowController? Пожалуйста, поделитесь этим.
Anoop Vaidya

Ответы:

410

Все эти команды вызываются автоматически в соответствующее время iOS, когда вы загружаете / представляете / скрываете контроллер представления. Важно отметить, что эти методы привязаны, UIViewControllerа не к UIViewсамим себе. Вы не получите ни одной из этих функций, просто используя UIView.

Там здорово документация на сайте компании Apple здесь . Вставляя просто, хотя:

  • ViewDidLoad- Вызывается при создании класса и загрузке из XIB. Отлично подходит для первоначальной настройки и разовой работы.

  • ViewWillAppear- Вызывается непосредственно перед отображением вашего представления, хорошо для скрытия / отображения полей или любых операций, которые вы хотите выполнять каждый раз, когда представление становится видимым. Поскольку вы можете переходить от одного представления к другому и обратно, оно будет вызываться каждый раз, когда ваше представление собирается появиться на экране.

  • ViewDidAppear - Вызывается после появления представления - отличное место для запуска анимации или загрузки внешних данных из API.

  • ViewWillDisappear/ DidDisappear- Та же идея, что и ViewWillAppear/ ViewDidAppear.

  • ViewDidUnload/ ViewDidDispose- В Objective-C, это то место, где вы выполняете очистку и освобождение материала, но это обрабатывается автоматически, так что вам не нужно ничего делать здесь.

Джейкоб Кнобель
источник
86
Этот текст немного вводит в заблуждение, поскольку ViewDidLoad не следует использовать для одноразовой работы. Он может вызываться несколько раз, если представление выгружается из-за нехватки памяти, а затем загружается снова.
Рикки Хелгессон
4
ViewDidLoad фактически не вызывается при создании / инициализации контроллера представления. Он вызывается в первый раз, когда вы делаете что-либо представление, связанное с представлением контроллера представления. Как добавить его в качестве подпредставления, установить кадр и т. Д. Он также вызывается, конечно, при загрузке из пера.
Джейсон Гранделли
3
ViewDidAppear - вызывается после появления представления - отличное место для запуска анимации или загрузки внешних данных из API. Почему это хорошее место для начала загрузки данных? Почему бы не viewDidLoad?
Антон Чикин
1
как насчет метода loadView, если он вызывается впервые, когда перо загружается в память перед viewDidLoad или нет.
iHulk
@chakrit это хорошая точка зрения - viewDidAppear - отличное место для обновления данных (если вам нужно). Я не согласен с KVO, потому что это может привести к нежелательному обновлению представлений, которые пользователь фактически никогда не просматривает.
Антон Чикин
409

ОБНОВЛЕНИЕ: ViewDidUnload устарела в iOS 6, поэтому обновил ответ соответственно.

Жизненный цикл UIViewController представлен здесь:

Жизненный цикл контроллера представления в виде диаграммы

Преимущество использования Xamarin Native / Mono Touch заключается в том, что он использует собственные API-интерфейсы и, следовательно, следует тому же жизненному циклу ViewController, что и в документации Apple.

Хайдер
источник
17
Куда идут viewWillLayoutSubviews и viewDidLayoutSubviews на этой потоковой диаграмме?
Max_Power89
7
Эта диаграмма неточна. viewDidUnload устарела с iOS6: stackoverflow.com/questions/12509102/…
occulus
2
Это действительно просто неправильно . Еще один пример просто неправильного ответа на SO, как проходят годы. Вычисления очень нестатичны.
Толстяк
186

Это для последних версий iOS (изменено с помощью Xcode 9.3, Swift 4.1 ). Ниже приведены все этапы, которые делают жизненный цикл UIViewControllerполным.

  • loadView()

  • loadViewIfNeeded()

  • viewDidLoad()

  • viewWillAppear(_ animated: Bool)

  • viewWillLayoutSubviews()

  • viewDidLayoutSubviews()

  • viewDidAppear(_ animated: Bool)

  • viewWillDisappear(_ animated: Bool)

  • viewDidDisappear(_ animated: Bool)

Позвольте мне объяснить все эти этапы.

1. loadView

Это событие создает / загружает представление, которым управляет контроллер. Он может загружаться из связанного файла пера или пустого файла, UIViewесли был найден ноль. Это делает его хорошим местом для программного создания ваших представлений в коде.

Здесь подклассы должны создавать свою собственную иерархию представлений, если они не используют перо. Никогда не должен вызываться напрямую. Переопределяйте этот метод только при программном создании представлений и назначении корневого представления viewсвойству. Не вызывайте супер-метод при переопределении loadView.

2. loadViewIfNeeded

Если incase представление current viewControllerеще не было установлено, тогда этот метод загрузит представление, но помните, это доступно только в iOS> = 9.0. Так что, если вы поддерживаете iOS <9.0, то не ожидайте, что она войдет в картину.

Загружает представление контроллера представления, если оно еще не было установлено.

3. viewDidLoad

viewDidLoadСобытие вызывается только тогда , когда вид создается и загружается в память , но границы для представления еще не определены. Это хорошее место для инициализации объектов, которые будет использовать контроллер представления.

Вызывается после того, как представление было загружено. Для контроллеров представления, созданных в коде, это после -loadView. Для контроллеров представления, разархивированных с пера, это после того, как представление установлено.

4. viewWillAppear

Это событие уведомляет viewControllerвсякий раз, когда представление появляется на экране. На этом шаге у представления есть границы, которые определены, но ориентация не установлена.

Вызывается, когда представление собирается сделать видимым. По умолчанию ничего не делает.

5. viewWillLayoutSubviews

Это первый шаг в жизненном цикле, когда границы завершаются. Если вы не используете ограничения или Auto Layout, вы, вероятно, захотите обновить подпредставления здесь. Это доступно только в iOS> = 5.0. Так что, если вы поддерживаете iOS <5.0, то не ожидайте, что она войдет в картину.

Вызывается непосредственно перед вызовом метода layoutSubviews представления контроллера представления. Подклассы могут реализовывать по мере необходимости. По умолчанию используется nop.

6. viewDidLayoutSubviews

Это событие уведомляет контроллер представления о том, что подпредставления были настроены. Это хорошее место для внесения любых изменений в подпредставления после их установки. Это доступно только в iOS> = 5.0. Так что, если вы поддерживаете iOS <5.0, то не ожидайте, что она войдет в картину.

Вызывается сразу после вызова метода layoutSubviews представления контроллера представления. Подклассы могут реализовывать по мере необходимости. По умолчанию используется nop.

7. viewDidAppear

На viewDidAppearсобытие срабатывает после представления представлен на экране. Что делает его хорошим местом для получения данных из бэкэнд-сервиса или базы данных.

Вызывается, когда вид полностью перешел на экран. По умолчанию ничего не делает

8. viewWillDisappear

В viewWillDisappearсобытие срабатывает , когда вид представлен viewControllerвот - вот исчезнет, увольте, крышку или спрятаться за другой viewController. Это хорошее место, где вы можете ограничить свои сетевые вызовы, сделать недействительным таймер или освободить объекты, которые связаны с этим viewController.

Вызывается, когда вид закрывается, скрывается или иным образом скрывается.

9. viewDidDisappear

Это последний шаг жизненного цикла, к которому любой может обратиться, поскольку это событие происходит сразу после того, как представление представленного объекта viewControllerисчезло, было отклонено, скрыто или скрыто.

Вызывается после того, как представление было закрыто, скрыто или иным образом скрыто. По умолчанию ничего не делает

Теперь, согласно Apple, когда вы реализуете эти методы, вы должны помнить, чтобы вызывать superреализацию этого конкретного метода.

Если вы подкласс UIViewController, вы должны вызвать супер реализацию этого метода, даже если вы не используете NIB. (Для удобства метод init по умолчанию сделает это за вас, и для обоих аргументов этого метода будет указано значение nil.) В указанном NIB прокси-серверу владельца файла должен быть установлен класс для вашего подкласса контроллера представления с выходом представления подключен к основному виду. Если вы вызываете этот метод с именем nil nib, -loadViewметод этого класса попытается загрузить NIB, имя которого совпадает с классом вашего контроллера представления. Если такого NIB на самом деле не существует, вы должны либо вызвать его -setView:до -viewвызова, либо переопределить -loadViewметод для программной настройки ваших представлений.

Надеюсь, это помогло. Спасибо.

ОБНОВЛЕНИЕ - Как @ThomasW указал внутри комментария, так viewWillLayoutSubviewsи viewDidLayoutSubviewsбудет вызываться в другое время, когда загружаются подпредставления основного представления, например, когда загружаются ячейки табличного представления или представления коллекции.

ОБНОВЛЕНИЕ - Как @Maria указал внутри комментария, описание loadViewбыло обновлено

по окончании
источник
6
viewWillLayoutSubviewsи viewDidLayoutSubviewsтакже будет вызываться в другое время, когда загружаются подпредставления основного представления, например, когда загружаются ячейки табличного представления или представления коллекции.
ThomasW
В этом ответе есть небольшое заблуждение: всегда вызывается loadView (), его просто не следует переопределять при создании представления для контроллера, созданного в IB.
Мария
@Maria Пожалуйста, отредактируйте ответ, если считаете, что его можно улучшить. Спасибо.
завершении
По умолчанию ничего не значит неправильно viewWillAppear viewDidAppear viewDidDisappear. Вы должны позвонить супер в какой-то момент.
Мик
47

iOS 10,11 (Swift 3.1, Swift 4.0)

По словам UIViewControllerв UIKitразработчиках,

1. loadView ()

Здесь подклассы должны создавать свою собственную иерархию представлений, если они не используют перо . Никогда не должен вызываться напрямую.

2. loadViewIfNeeded ()

Загружает представление контроллера представления, если оно еще не было установлено.

3. viewDidLoad ()

Вызывается после того, как представление было загружено. Для контроллеров представления, созданных в коде, это после -loadView. Для контроллеров представления, разархивированных с пера, это после того, как представление установлено.

4. viewWillAppear (_ animated: Bool)

Вызывается, когда представление собирается сделать видимым. По умолчанию ничего не делает

5. viewWillLayoutSubviews ()

Вызывается непосредственно перед вызовом метода layoutSubviews представления контроллера представления. Подклассы могут реализовывать по мере необходимости. По умолчанию ничего не делает.

6. viewDidLayoutSubviews ()

Вызывается сразу после вызова метода layoutSubviews представления контроллера представления. Подклассы могут реализовывать по мере необходимости. По умолчанию ничего не делает.

7. viewDidAppear (_ animated: Bool)

Вызывается, когда вид полностью перешел на экран. По умолчанию ничего не делает

8. viewWillDisappear (анимированный: Bool)

Вызывается, когда вид закрывается, скрывается или иным образом скрывается. По умолчанию ничего не делает

9. viewDidDisappear (анимированный: Bool )

Вызывается после того, как представление было закрыто, скрыто или иным образом скрыто. По умолчанию ничего не делает

10. viewWillTransition (для размера: CGSize, с координатором: UIViewControllerTransitionCoordinator)

Вызывается, когда представление переходное.

11. willMove (родительский элемент toParentViewController: UIViewController?)

12. didMove (родительский элемент toParentViewController: UIViewController?)

Эти два метода общедоступны для вызова подклассов контейнера при переходе между дочерними контроллерами. Если они переопределены, переопределения должны обеспечить вызов супер.

Аргумент parent в обоих этих методах равен nil, когда дочерний элемент удаляется из родительского элемента; в противном случае он равен новому родительскому контроллеру представления.

13. didReceiveMemoryWarning ()

Вызывается, когда родительское приложение получает предупреждение о памяти. На iOS 6.0 он больше не будет очищать вид по умолчанию.

Раджамохан С
источник
2
Действительно действительно достаточно того, что stackoverflow не удалит все неправильные и неполные ответы из всей этой цепочки. Ваш ответ кажется полным в том, что касается вызовов методов, так что я собираюсь предположить, что ваш ответ правильный и работать с этим.
Логиксавр Рекс
Что такое nibкак упомянуто под loadView?
Петрус Терон
2
@LogicsaurusRex Я согласен. Точно так же, как SO помечает вопросы как дубликаты или как защищенные, я думаю, что он должен иметь возможность помечать ответы как устаревшие или устаревшие
rmp251
Пункт 5 выше неверен. viewWillLayoutSubviews()вызывается до того, как объект представления ViewController вызывает его layoutSubviews()метод
williamukoh
28

Начиная с iOS 6 и выше. Новая диаграмма выглядит следующим образом:

введите описание изображения здесь

Саад
источник
1
Назовите это представление "A". Рассмотрим второе представление «B», которое появляется, когда «A» исчезает. Является ли B.viewWillAppear до или после A.viewDidDisappear? И есть ли ситуации, когда порядок этих двух меняется?
ToolmakerSteve
Похоже, что новое представление (B) willApear будет вызвано до появления disAppears. Для второго вопроса. Нужно время, чтобы разобраться в этом.
Саад
21

Давайте сосредоточимся на методах, отвечающих за жизненный цикл UIViewController :

  • Создание:

    - (void)init

    - (void)initWithNibName:

  • Просмотр создания:

    - (BOOL)isViewLoaded

    - (void)loadView

    - (void)viewDidLoad

    - (UIView *)initWithFrame:(CGRect)frame

    - (UIView *)initWithCoder:(NSCoder *)coder

  • Обработка изменения состояния просмотра:

    - (void)viewDidLoad

    - (void)viewWillAppear:(BOOL)animated

    - (void)viewDidAppear:(BOOL)animated

    - (void)viewWillDisappear:(BOOL)animated

    - (void)viewDidDisappear:(BOOL)animated

    - (void)viewDidUnload

  • Обработка предупреждений памяти:

    - (void)didReceiveMemoryWarning

  • Deallocation

    - (void)viewDidUnload

    - (void)dealloc

Диаграмма жизненного цикла UIViewController

Для получения дополнительной информации, пожалуйста, взгляните на UIViewController Class Reference .

Алексей Пелех
источник
19

Методы viewWillLayoutSubviewsи viewDidLayoutSubviewsне упоминаются в диаграммах, но они вызываются между viewWillAppearи viewDidAppear. Их можно вызывать несколько раз.

gjgjgj
источник
Они также будут вызываться в другое время при загрузке подпредставлений основного представления, например при загрузке ячеек табличного представления или представления коллекции.
ThomasW
16

Ответ Хайдера является правильным для предварительной версии iOS 6. Однако, начиная с iOS 6, viewDidUnload и viewWillUnload никогда не вызываются. Документы состояние: «Просмотры более не продувает в условиях низкой памяти и поэтому этот метод никогда не вызывается.»

Мэтт Беккер
источник
Я попытался поставить точку останова в ViewWillDisappear, ViewDidDisappear, Dispose. Но ни один из них не вызывался, когда я перемещался с помощью метода PresentViewController (). Что может быть причиной ?
Sreeraj
1
Ссылка не работает ... Так что же делать ОС при нехватке памяти?
Сын
Сохраняет их на диск?
Ян Уорбертон
16

Здесь много устаревшей и неполной информации. Только для iOS 6 и новее :

  1. loadView[А]
  2. viewDidLoad[А]
  3. viewWillAppear
  4. viewWillLayoutSubviews это первый раз, когда границы завершены
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. * viewWillLayoutSubviews[Ь]
  8. * viewDidLayoutSubviews[Ь]

Примечания:

(а) - Если вы вручную NIL ваш взгляд во время didReceiveMemoryWarning, loadViewи viewDidLoadбудет называться снова. То есть по умолчанию loadViewи вызывается viewDidLoadтолько один раз для каждого экземпляра контроллера представления.

(б) Может вызываться дополнительно 0 или более раз.

bobics
источник
1
viewWillLayoutSubviewsи viewDidLayoutSubviewsтакже будет вызываться в другое время, когда загружаются подпредставления основного представления, например, когда загружаются ячейки табличного представления или представления коллекции.
ThomasW
11

Объяснение переходов между состояниями в официальном документе: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html.

На этом изображении показаны действительные переходы между различными методами обратного вызова «will» и «did».

Действительные государственные переходы:


Взято из: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController класса Reference_2x.png

Луисми
источник
0

Согласно документу Apple - Начните разрабатывать приложения для iOS (Swift) - Работайте с контроллерами представления - Поймите жизненный цикл контроллера представления

viewDidLoad()- Вызывается, когда представление содержимого контроллера представления (верхняя часть его иерархии представления) создается и загружается из раскадровки. … Используйте этот метод для выполнения любых дополнительных настроек, требуемых вашим контроллером представления.

viewWillAppear()- Вызывается непосредственно перед тем, как представление контента контроллера представления добавляется в иерархию представления приложения. Используйте этот метод для запуска любых операций, которые должны произойти до того, как представление контента будет представлено на экране

viewDidAppear()- Вызывается сразу после добавления представления содержимого контроллера представления в иерархию представления приложения. Используйте этот метод для запуска любых операций, которые должны произойти, как только представление будет отображено на экране, таких как выборка данных или отображение анимации.

viewWillDisappear()- Вызывается непосредственно перед удалением представления содержимого контроллера представления из иерархии представления приложения. Используйте этот метод для выполнения задач очистки, таких как принятие изменений или отказ от статуса первого респондента.

viewDidDisappear()- Вызывается сразу после того, как представление контента контроллера представления было удалено из иерархии представления приложения. Используйте этот метод для выполнения дополнительных действий.

Фред
источник