viewWillAppear, viewDidAppear не вызывается, не запускается

(это и вопрос, и ответ, так как потребовалось довольно много копать, чтобы найти реальный ответ.)

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

причина: вложение 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/)

2 ответов


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

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

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

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

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

посыпать в некоторых 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 superview цепь до попадания ноль.

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

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

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

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

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

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


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

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

#warning I SHOULD NOT HAVE TO DO THIS!!

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

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