Подтвердить что ты не робот

ViewWillAppear, viewDidAppear не вызывается, а не стреляет

(Это и вопрос, и ответ, поскольку для поиска реального ответа потребовалось немало усилий).

Симптом: viewWillAppear, viewDidAppear не вызывались в моем UIViewController.

Причина. Вставка a UINavigationController или UITabBarController (мой случай) в UIViewController как-то прерывает вызов этих методов.

Решение. Вызовите их вручную в UIViewController, который содержит вышеупомянутый UINavigationController/UITabBarController.

Например (если projectNavigationController является вашим UINavigationController):

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [projectNavigationController viewWillAppear:animated];
}

-(void)viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated];
    [projectNavigationController viewWillDisappear:animated];
}

-(void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated];
    [projectNavigationController viewDidAppear:animated];
}

-(void)viewDidDisappear:(BOOL)animated { 
    [super viewDidDisappear:animated];
    [projectNavigationController viewDidDisappear:animated];
}

В моем случае у меня был внутренний UITabBarController, и я назвал методы соответствующим образом, и все было решено.

(Атрибуция по решению: http://davidebenini.it/2009/01/03/viewwillappear-not-being-called-inside-a-uinavigationcontroller/)

4b9b3361

Ответ 1

Я собираюсь пойти дальше и не согласиться с @St3fan и использовать UIKit в качестве контр-примера.

Однако мудрость (или ее отсутствие) встроенных контроллеров в целом должна основываться на нормальных принципах дизайна пользовательского интерфейса.

Самый простой встречный пример - UINavigationControllers, встроенный в UITabBarControllers. Они появляются повсюду. Сверху от головы, приложение iPod на iPhone и контакты в приложении Phone на iPhone.

Мне было любопытно узнать, что они делают с представлениями (добавить к представлению "суперконтроллер" или к UIWindow. Я был уверен, что я собираюсь найти, что представления подконтроллеров были потомки представлений суперконтроллера в иерархии представлений, что противоречит рекомендации St3fan.

Я взломал очень быстрое приложение для iPhone, подключая все в интерфейсе InterfaceBuilder для создания приложения на основе UITabBarController с двумя вкладками, первым из которых был UINavigationController с простым ole UIViewController в качестве контроллера корневого представления, и вторую вкладку с простым старым UIViewController, так что у меня была вторая вкладка, чтобы щелкнуть позже.

Посыпьте несколько операторов NSLog для вывода различных UIView's для контроллеров, которые мы видим:

tabBarController.view = <UILayoutContainerView: 0x5b0dc80; ...
navigationController.view = <UILayoutContainerView: 0x59469a0; ...
rootViewController.view = <UIView: 0x594bb70; ...
Superview: <UIViewControllerWrapperView: 0x594cc90; ...
Superview: <UINavigationTransitionView: 0x594a420; ...
Superview: <UILayoutContainerView: 0x59469a0; ... // navigationController.view
Superview: <UIViewControllerWrapperView: 0x594b430; ...
Superview: <UITransitionView: 0x5b0e110; ...
Superview: <UILayoutContainerView: 0x5b0dc80; ... // tabBarController.view
Superview: <UIWindow: 0x5942a30; ...

Линии, предваряемые "Superview", были результатом перехода вверх по цепочке супервизора rootViewController.view's, пока не достигнут нулевой.

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

Во-первых, стек вызовов, когда viewDidDisappear вызывается в корневом контроллере в результате перехода нового контроллера в стек:

-[RootController viewDidDisappear:]
-[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:]
...

Во-вторых, стек вызовов, когда другая вкладка выбрана в самом верхнем UITabBarController:

-[RootController viewDidDisappear:]
-[UINavigationController viewDidDisappear:]
-[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:]

Поэтому во всех случаях кажется, что Apple решила, что контроллеры должны вызывать различные методы viewDidAppear и т.д. на своих встроенных субконтроллерах и что представление должно быть встроено аналогично. Я думаю, что OP поражает этот гвоздь прямо на голове, если мы хотим принять UIKit дизайн как хорошее руководство для последующего.

Ответ 2

Я только что увидел то же самое обстоятельство. Раньше сеанс компоновщика интерфейса, вызванный выбором ячейки таблицы, прекратил работу, и после некоторого раздражения, копающегося в коде, я просто установил его вручную, вызывая из переопределения выбора ячейки в представлении представления таблицы.

Позднее я сделал некоторые изменения компоновки в вызываемом контроллере представления и увидел, что viewDidAppear не вызывался, как описано выше. Отладочный вывод ссылался на "вложенные push-операции" или что-то в этом роде, и поскольку у меня был большой комментарий к себе в моей операции ручного нажатия

#warning I SHOULD NOT HAVE TO DO THIS!!

Я остановил код segue, и, конечно же, IB segue теперь работал, и это была моя ручная операция в коде выбора ячейки таблицы, которая испортила вызовы делегатов в вызываемом представлении. Я удалил ручной код, и все в порядке.

Кажется странным, что код выбора ячейки вызывает вызов после нажатия представления. Я должен сделать протокол и делегировать, чтобы получить индексный путь выбранной ячейки в вызывающем.