viewWillAppear,viewDidAppear没有被调用,没有被触发

时间:2010-08-24 20:16:19

标签: iphone objective-c uitabbarcontroller viewwillappear

(这是问题和答案,因为需要花费大量时间才能找到真正的答案。)

症状:我的UIViewController中没有调用viewWillAppearviewDidAppear

原因:在UINavigationController中嵌入UITabBarControllerUIViewController(我的情况)会以某种方式中断调用这些方法。

解决方案:在包含前述UIViewController / UINavigationController的{​​{1}}中手动调用它们。

例如(假设UITabBarController是您的projectNavigationController):

-(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];
}

在我的情况下,我有一个内部UINavigationController,我相应地调用了这些方法,所有这些都得到了解决。

(解决方案的归因:http://davidebenini.it/2009/01/03/viewwillappear-not-being-called-inside-a-uinavigationcontroller/

2 个答案:

答案 0 :(得分:10)

我将继续并且不同意@ St3fan,并使用UIKit作为反例。

然而,嵌入式控制器的智慧(或缺乏)应该遵循理智的UI设计原则。

最简单的反例是UINavigationControllers嵌入UITabBarControllers。这些出现在各处。就在我脑海中,iPhone上的iPod应用程序和iPhone上的手机应用程序中的联系人。

我很好奇,懒得去查看他们对视图做了什么(添加到“超级控制器”视图或UIWindow。我很确定我会找到子控制器视图是视图层次结构中超级控制器视图的后代,这与St3fan的建议相反。

我掀起了一个非常快速的iPhone应用程序,在InterfaceBuilder中连接所有内容以创建一个基于UITabBarController的应用程序,其中包含两个标签,第一个是UINavigationController,内容为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等方法,并且应该以类似方式嵌入视图。我认为,如果我们将UIKit设计作为一个良好的领导者,那么OP就会立即发挥作用。

答案 1 :(得分:0)

我刚看到同样的情况。之前由表格单元格选择触发的界面构建器segue已经停止工作,并且在对代码进行一些恼怒之后,我只是手动设置它,从表格视图委托中的单元格选择覆盖调用。

稍后我在被调用的视图控制器中进行了一些布局更改,并看到没有调用viewDidAppear,如上所述。调试输出引用了“嵌套推送操作”或类似内容,因为我在手动推送操作中对自己有一个很大的评论

#warning I SHOULD NOT HAVE TO DO THIS!!

我打破了segue代码,当然,IB segue现在正在工作,这是我在表单元格选择代码中的手动操作,它扰乱了被调用视图中的委托调用。我删除了手动代码,一切都很好。

在推送视图后调用单元格选择代码似乎很奇怪。我必须做一个协议和委托来获取调用者中所选单元格的索引路径。