UIViewController viewDidLoad против viewWillAppear: Что такое правильное разделение труда?

164

Мне всегда было немного неясно, какие задачи следует назначать для « viewDidLoadпротив» viewWillAppearв UIViewControllerподклассе.

Например, я делаю приложение, в котором у меня есть UIViewControllerподкласс, работающий с сервером, получающий данные, передающий их в представление и затем отображающий это представление. Каковы плюсы и минусы делать это в viewDidLoadVS. viewWillAppear?

dugla
источник

Ответы:

251

viewDidLoad - это то, что вы должны сделать один раз. viewWillAppear вызывается каждый раз, когда появляется представление. Вы должны делать то, что вам нужно сделать только один раз в viewDidLoad - например, устанавливать тексты UILabel. Однако вы можете захотеть изменять определенную часть представления каждый раз, когда пользователь просматривает ее, например, приложение iPod прокручивает текст обратно вверх, каждый раз, когда вы переходите к представлению «Сейчас исполняется».

Тем не менее, когда вы загружаете вещи с сервера, вы также должны думать о задержке. Если вы упакуете все свои сетевые коммуникации в viewDidLoad или viewWillAppear, они будут выполнены до того, как пользователь увидит представление, что может привести к кратковременному зависанию вашего приложения. Это может быть хорошей идеей, чтобы сначала показать пользователю незаселенный вид с каким-либо индикатором активности. Когда вы закончите работу с сетью, что может занять секунду или две (или может даже потерпеть неудачу - кто знает?), Вы можете заполнить представление своими данными. Хорошие примеры того, как это можно сделать, можно увидеть в различных клиентах Twitter. Например, при просмотре страницы сведений об авторе в Twitterrific в представлении отображается только «Загрузка ...» до тех пор, пока не завершатся сетевые запросы.

LeonBrussels
источник
Итак, относительно viewWillAppear потенциально вызывается неоднократно. Будет ли этот метод срабатывать, если, например, представление viewcontrollers стало видимым после того, как оно было скрыто (я имею в виду здесь скрытый, а не скрытый метод в UIView). В каком сценарии будет вызываться viewWillAppear без предшествующего вызова viewDidLoad?
Дугла
7
viewDidLoad вызывается ТОЛЬКО при построении представления - например, после вызова initFromNibNamed контроллера представления при обращении к представлению. viewWillAppear вызывается каждый раз, когда ваш контроллер представления не был виден, но появляется в представлении - поэтому, когда ваш контроллер представления нажат, вызывается viewWillAppear. Если вы отправите оттуда другое подпредставление, и пользователь вернется, viewWillAppear вызывается снова.
Кендалл Хельмштеттер Гелнер
Спасибо Кендалл. Да, несколько стратегически расположенных NSLogs помогли мне разобраться. viewWillAppear / viewWillDissappear огонь на push / pops контроллера контроллера
Дугла
3
Обратите внимание, что viewDidLoad ТАКЖЕ будет вызываться, если представление скрыто, а затем выгружено по причинам, связанным с памятью, а затем появляется снова. То, на что вы можете рассчитывать: viewDidLoad будет называться по крайней мере ОДИН РАЗ, когда вид создается впервые, и ВОЗМОЖНО больше раз, когда вид снова появляется после его скрытия. viewWillAppear будет ВСЕГДА вызываться, когда представление собирается появиться на экране.
ДанМ
2
Может кто-то прокомментировать, пожалуйста, эти два связанных вопроса: (1) Иногда, не всегда, значения фреймов для элементов управления (то есть, происхождение и размер) равны нулю в viewDidLoad, а иногда нет - Почему? (2) В шаблоне Apple для detailView splitViewController (iPad) есть метод configureView - что должно быть там относительно viewDidLoad и ViewWillAppear?
Джефф
12

Изначально использовался только ViewDidLoad с tableView. При тестировании с потерей Wi-Fi, установив устройство в режим полета, понял, что таблица не обновилась с возвратом Wi-Fi. Фактически, по-видимому, нет способа обновить tableView на устройстве, даже нажав кнопку home с фоновым режимом, установленным в YES в -Info.plist.

Мое решение:

-(void) viewWillAppear: (BOOL) animated { [self.tableView reloadData];}
Jaminyah
источник
10

Важно отметить, что использование viewDidLoad для позиционирования немного рискованно, и его следует избегать, поскольку границы не установлены. это может привести к неожиданным результатам (у меня было множество проблем ...)

Этот пост довольно хорошо описывает различные методы и то, что происходит в каждом из них.

В настоящее время для одноразового инициализации и позиционирования я подумываю использовать viewDidAppear с флагом, если у кого-то есть другие рекомендации, пожалуйста, дайте мне знать.

keisar
источник
согласен с этим: «... следует избегать, так как границы не установлены ...»
danisupr4
4

Зависит, нужно ли вам загружать данные каждый раз, когда вы открываете представление? или только один раз ?

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

  • Красный: они не требуют менять каждый раз. Как только они загружены, они остаются такими, какими они были.
  • Фиолетовый: они должны меняться со временем или после загрузки каждый раз. Вы не хотите видеть тех же 3 предложенных пользователей, которым нужно следовать, их нужно перезагружать каждый раз, когда вы возвращаетесь на экран. Их фотографии могут обновляться ... Вы не хотите видеть фотографию 5 лет назад ...

viewDidLoad: Какую бы обработку вы ни выполняли, это нужно сделать один раз.
viewWilLAppear:Независимо от обработки, которая должна меняться при каждой загрузке страницы.

Метки, значки, названия кнопок или большинство dataInputedByDeveloper обычно не меняются. Имена, фотографии, ссылки, статус кнопок, списки (входные массивы для ваших таблиц или коллекций) или большинство dataInputedByUser обычно меняются.

Мед
источник
Фиолетовый будет вызываться в viewDidAppear, а не viewWillAppear
Алекс Корнхаузер
@AlexKornhauser что ты имеешь ввиду под названием? Я говорю, что viewWillAppearвы можете запросить и проверить последние твиты. viewDidAppearслишком поздно для этого
мед