В чем разница между -[UIViewController viewWillAppear:]
и -[UIViewController viewDidAppear:]
?
В чем разница между -[UIViewController viewWillAppear:]
и -[UIViewController viewDidAppear:]
?
Ответы:
В общем, что делаю:
1) ViewDidLoad - всякий раз, когда я добавляю элементы управления к представлению, которое должно отображаться вместе с представлением, я сразу же помещаю его в метод ViewDidLoad. Обычно этот метод вызывается всякий раз, когда представление загружается в память. Так, например, если мое представление представляет собой форму с 3 метками, я бы добавил сюда метки; представление никогда не будет существовать без этих форм.
2) ViewWillAppear : обычно я использую ViewWillAppear только для обновления данных в форме. Итак, в приведенном выше примере я бы использовал это, чтобы фактически загрузить данные из моего домена в форму. Создание UIViews довольно дорогое, и вам следует по возможности избегать этого в методе ViewWillAppear, потому что когда он вызывается, это означает, что iPhone уже готов показать UIView пользователю, и все, что вы здесь делаете будет заметно влиять на производительность (например, задержка анимации и т. д.).
3) ViewDidAppear : наконец, я использую ViewDidAppear для запуска новых потоков к вещам, выполнение которых потребует много времени, например, выполнение вызова веб-службы для получения дополнительных данных для формы выше. Хорошо то, что, поскольку представление уже существует и отображается для пользователя, вы можете показать пользователю приятное сообщение «Ожидание», пока вы получаете данные.
viewWillAppear
? Вы имеете ввиду скачивание через сеть? Но вы также предлагаете загружать файлы viewDidAppear
?
ViewDidAppear
вы легко запутаете пользователя в пользовательском интерфейсе :)
viewDidLoad === >>> Поместите сюда свой код инициализации. Не помещайте динамические данные, которые могут измениться в течение жизненного цикла представления. Итак, если вы извлекаете данные из основных данных, вы не хотите делать это здесь, если это может измениться в течение жизни представления. Например: скажем, у вас есть контроллер вкладок. Вы переключаетесь с tab1 на tab2 и что-то меняете в модели на tab2. Если вы вернетесь к tab1 и код вашей модели был выполнен в viewDidLoad, он не будет обновлен (при условии, что вы не используете KVO или NSFetchedResultsController и т. Д.).
viewWillAppear === >>> Это вызывается каждый раз, когда представление собирается появиться, вне зависимости от того, находится оно уже в памяти или нет. Поместите сюда свой динамический код, например логику модели.
viewDidAppear === >>> Поместите сюда дорогостоящие операции, которые вы хотите выполнять, только если вы уверены, что представление находится на экране, например, сетевые вызовы.
Примечание: если ваше приложение находится в фоновом режиме и возвращается на передний план, вам необходимо обработать это с помощью NSNotificationCenter. Я написал код для этого в комментариях ниже. Вы можете подумать, что viewWillAppear / viewDidAppear сработает. Поставьте там точку останова и проверьте ее. Не стреляет. Итак, если что-то изменилось в вашем приложении, пока оно работало в фоновом режиме, вам необходимо обновить это с помощью уведомлений.
viewWillAppear
Метод вызывается перед загрузкой фактического представления.
viewDidAppear
Метод вызывается , когда представление уже загружен, и вы хотите , чтобы показать что - то.
viewWillAppear:
■ Вызывается перед добавлением представления в иерархию представлений окон
■ Вызывается перед [vc.view layoutSubviews] (при необходимости)
viewDidAppear :
■ Вызывается после добавления представления в иерархию представлений
■ Вызывается после [vc.view layoutSubviews] (если необходимо)
Несколько замечаний:
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
. Если переход отменен, этого не произойдет.
1) ViewWillAppear : представление, фактически загруженное в память, вызывается один раз в контроллере представления и имеет свой фрейм, но все еще не отображается для пользователя
2) ViewDidAppear : контроллер, добавленный в иерархию представлений, чтобы вы могли представить их следующему контроллеру, а также представление компоновало подвиды.
Первое происходит до появления представления, а второе - после.
Подводить итоги:
-viewWillAppear -> обновить данные (перезагрузить данные из табличного представления)
-viewDidAppear -> дорогие операции (вызов API с хорошим индикатором прогресса!)
Вариант использования , т.е. когда я должен использовать какой?
viewDidLoad
- когда метки, кнопки (т.е. любые элементы управления / подпредставления) подключены к файлу интерфейса представления, и если вы хотите загрузить все это одновременно с представлением ViewController, и если вы хотите загрузить это в память один раз и быть покончено с этим
viewWillAppear
- скажем, вы хотите изменять цвет фона представления каждый раз, когда на экране появляется viewController. Или, что более реалистично, если вам нужен цвет фона DarkMode в ночное время дня и светлый цвет фона в дневное время, используйте этот код вviewWillAppear
Еще один хороший вариант использования здесь https://stackoverflow.com/a/39395865/5438240
Также обратите внимание, что, если вы используете стек навигации ( UINavigationController
), viewController, который должен быть извлечен, имеет viewWillDisappear()
вызываемый, а ViewController, который в следующий раз будет на вершине стека, будет viewWillAppear()
вызывать