В чем разница между -viewWillAppear: и -viewDidAppear :?


131

В чем разница между -[UIViewController viewWillAppear:]и -[UIViewController viewDidAppear:]?


1
спасибо BoltClock, но, пожалуйста, дайте мне пример того и другого, если возможно ..
PJR

3
@BoltClock было бы неплохо, если бы это было правдой. Я предполагаю, что 15 человек, проголосовавших за, прочитали название метода, но никогда не измерили его ... Пришли сюда из Google, потому что это НЕ разница между ними
Адам

1
В частности: parentView.viewDidAppear вызывается ДОЛГОЕ ВРЕМЯ до того, как Apple фактически отображает parentView ... Apple сначала (атомарно) рисует все подпредставления ... и если у вас много подпредставлений или сложных, тогда "viewDidAppear" можно назвать десятками или на сотни миллисекунд раньше :(.
Адам

Ответы:


292

В общем, что делаю:

1) ViewDidLoad - всякий раз, когда я добавляю элементы управления к представлению, которое должно отображаться вместе с представлением, я сразу же помещаю его в метод ViewDidLoad. Обычно этот метод вызывается всякий раз, когда представление загружается в память. Так, например, если мое представление представляет собой форму с 3 метками, я бы добавил сюда метки; представление никогда не будет существовать без этих форм.

2) ViewWillAppear : обычно я использую ViewWillAppear только для обновления данных в форме. Итак, в приведенном выше примере я бы использовал это, чтобы фактически загрузить данные из моего домена в форму. Создание UIViews довольно дорогое, и вам следует по возможности избегать этого в методе ViewWillAppear, потому что когда он вызывается, это означает, что iPhone уже готов показать UIView пользователю, и все, что вы здесь делаете будет заметно влиять на производительность (например, задержка анимации и т. д.).

3) ViewDidAppear : наконец, я использую ViewDidAppear для запуска новых потоков к вещам, выполнение которых потребует много времени, например, выполнение вызова веб-службы для получения дополнительных данных для формы выше. Хорошо то, что, поскольку представление уже существует и отображается для пользователя, вы можете показать пользователю приятное сообщение «Ожидание», пока вы получаете данные.


4
Извините, но что вы имеете в виду, говоря «загрузить данные из моего домена в форму» viewWillAppear? Вы имеете ввиду скачивание через сеть? Но вы также предлагаете загружать файлы viewDidAppear?
Philip007

1
@ Philip007 Я думаю, что Стек имеет в виду домен такого типа: en.wikipedia.org/wiki/Domain-specific_modeling . Данные загружаются из ваших моделей или аналогичных.
dentarg

2
Этот ответ должен быть в документации. Это действительно помогло прояснить разницу между тремя методами. Спасибо!
GangstaGraham

1
+1 Я немного запутался, понимая разницу между этими тремя, но вы только что прояснили это более чем идеально @ChetanBhalara
Chisx

@ChetanBhalara, но если вы будете много работать над этим, ViewDidAppearвы легко запутаете пользователя в пользовательском интерфейсе :)
hqt

46

viewDidLoad === >>> Поместите сюда свой код инициализации. Не помещайте динамические данные, которые могут измениться в течение жизненного цикла представления. Итак, если вы извлекаете данные из основных данных, вы не хотите делать это здесь, если это может измениться в течение жизни представления. Например: скажем, у вас есть контроллер вкладок. Вы переключаетесь с tab1 на tab2 и что-то меняете в модели на tab2. Если вы вернетесь к tab1 и код вашей модели был выполнен в viewDidLoad, он не будет обновлен (при условии, что вы не используете KVO или NSFetchedResultsController и т. Д.).

viewWillAppear === >>> Это вызывается каждый раз, когда представление собирается появиться, вне зависимости от того, находится оно уже в памяти или нет. Поместите сюда свой динамический код, например логику модели.

viewDidAppear === >>> Поместите сюда дорогостоящие операции, которые вы хотите выполнять, только если вы уверены, что представление находится на экране, например, сетевые вызовы.

Примечание: если ваше приложение находится в фоновом режиме и возвращается на передний план, вам необходимо обработать это с помощью NSNotificationCenter. Я написал код для этого в комментариях ниже. Вы можете подумать, что viewWillAppear / viewDidAppear сработает. Поставьте там точку останова и проверьте ее. Не стреляет. Итак, если что-то изменилось в вашем приложении, пока оно работало в фоновом режиме, вам необходимо обновить это с помощью уведомлений.


1
Запускается ли ViewWill или ViewDid каждый раз, когда вы снимаете сворачивание приложения?
Jeef 02

2
@Jeef Это отличный вопрос. Ни один из них не запускается, если приложение не убито системой или пользователем в фоновом режиме. Что вам нужно сделать, чтобы получить уведомление, когда приложение не свернуто, вы должны использовать NSNotificationCenter и addObserver для имени UIApplicationWillEnterForegroundNotification. Селектор должен быть applicationWillEnterForeground: у него есть параметр NSNotification. Поместите свой код в этот метод для перезагрузки данных и т. Д. Что вы можете сделать, так это создать метод перезагрузки, который вы вызываете из этого метода, а также viewDidAppear, если они должны быть одинаковыми.
smileBot 02

2
@Jeef что-то вроде этого: - (void) viewDidLoad {[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector (applicationWillEnterForeground :) name: UIApplicationWillEnterForegroundNotification object: nil]; } - (void) applicationWillEnterForeground: (NSNotification *) notif {// ответить здесь чем угодно}
smileBot 02

12

viewWillAppearМетод вызывается перед загрузкой фактического представления.

viewDidAppearМетод вызывается , когда представление уже загружен, и вы хотите , чтобы показать что - то.


9

viewWillAppear:
■ Вызывается перед добавлением представления в иерархию представлений окон
■ Вызывается перед [vc.view layoutSubviews] (при необходимости)
viewDidAppear :
■ Вызывается после добавления представления в иерархию представлений
■ Вызывается после [vc.view layoutSubviews] (если необходимо)


7

Несколько замечаний:

  • viewDidLoadМетод вызывается , когда представление первого экземпляра. IBOutletссылки подключаются к моменту вызова, но не раньше. Однако frameточка зрения может не быть установлена ​​к тому времени, когда это было вызвано. Это отличное место для добавления / настройки подвидов и связанных с ними ограничений. Но если вы выполняете любую ручную настройку frameзначений на основе размеров основного представления, настройку этих фреймов следует отложить до viewWillAppearили viewDidLayoutSubviews.

  • viewWillAppearМетод вызывается , когда представление вида в иерархии представлений собирается начать. Примечательно, что это вызывается в начале анимации (если есть) представления представления. Его компаньон, viewWillDisappearочевидно , вызывается, когда начинается переход от этой точки зрения.

  • viewDidAppearМетод вызывается , когда делается презентация зрения, в частности , когда - либо , и все связанные с ним анимация завершена. Его компаньон, viewDidDisappearочевидно , вызывается, когда выполняется переход от этого представления.

Два важных предостережения:

  • viewDidLoadвызывается один раз и только один раз, когда представление создается впервые. С другой стороны, viewWillAppearи viewDidAppearбудет вызываться не только при первом представлении представления, но и каждый последующий раз при повторном представлении того же представления. Например, когда вы впервые представляете представление, будут вызваны все три этих метода. Если рассматриваемое представление впоследствии представляет другое представление, которое впоследствии отклоняется, viewWillAppearи viewDidAppearобычно будет вызываться снова, когда рассматриваемое представление добавляется и анимируется обратно в иерархию представлений, но viewDidLoadне будет. viewDidLoadвызывается только при первом создании этого конкретного экземпляра.

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

  • Вызов viewWillAppearне гарантирует, что переход к этому представлению когда-либо будет завершен. Примечательно, что если вы используете интерактивный переход, управляемый пользователем в режиме реального времени, но этот интерактивный переход можно отменить. Т.е. только потому, что viewWillAppearвызывается, это не значит, что viewDidAppearбудет вызван. Обычно это так, но если интерактивный жест отменяется, этого не происходит (потому что переход никогда не завершался).

    На WWDC 2013 в контексте интерактивных переходов ведущий пошутил, что их следует переименовать viewWillAppearв « viewMightAppear, или viewWillProbablyAppear, или iReallyWishThisViewWouldAppear».

    Примером встроенного интерактивного жеста является использование, UINavigationControllerи вы «проводите пальцем от левого края», чтобы инициировать всплывающее окно представления. viewWillAppearБудет вызываться для представления , к которому вы выскакивают, но если вы отмените , что «листайте левого края» , чтобы вернуться к просмотру , с которого вы начали это поп жест, поп отменяется , и viewDidAppearдля представления вы начали вернуться к никогда не будет вызван.

    В viewWillAppearитоге вы должны быть осторожны и не писать код, предполагающий, что за каждым вызовом в конечном итоге последует вызов viewDidAppear. Если переход отменен, этого не произойдет.


5

viewwillappear будет вызывать перед загрузкой представления, чтобы вы могли выполнить определенную задачу перед загрузкой этого представления, а viewdidappear вызовет после загрузки представления, чтобы задача публикации была выполнена в этом методе


4

Разница между «will» и «did» ... Как следует из названия, viewWillAppear вызывается до того, как представление собирается появиться, а viewDidAppear вызывается, когда представление действительно появилось.


посмотрите на принятый ответ, братан, который содержит 70+ голосов. :)
PJR

4

1) ViewWillAppear : представление, фактически загруженное в память, вызывается один раз в контроллере представления и имеет свой фрейм, но все еще не отображается для пользователя

2) ViewDidAppear : контроллер, добавленный в иерархию представлений, чтобы вы могли представить их следующему контроллеру, а также представление компоновало подвиды.



3

Подводить итоги:

-viewWillAppear -> обновить данные (перезагрузить данные из табличного представления)

-viewDidAppear -> дорогие операции (вызов API с хорошим индикатором прогресса!)


1

Как следует из названия, viewWillAppearвызывается перед тем, как представление собирается появиться, и viewDidAppearвызывается, когда представление действительно появилось.


0

Вариант использования , т.е. когда я должен использовать какой?

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

viewWillAppear- скажем, вы хотите изменять цвет фона представления каждый раз, когда на экране появляется viewController. Или, что более реалистично, если вам нужен цвет фона DarkMode в ночное время дня и светлый цвет фона в дневное время, используйте этот код вviewWillAppear

Еще один хороший вариант использования здесь https://stackoverflow.com/a/39395865/5438240

Также обратите внимание, что, если вы используете стек навигации ( UINavigationController), viewController, который должен быть извлечен, имеет viewWillDisappear()вызываемый, а ViewController, который в следующий раз будет на вершине стека, будет viewWillAppear()вызывать

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.