viewWillDisappear,viewWillAppear不调用的解决方法

viewWillDisappear,viewWillAppear不调用的解决方法

博客分类: iOS
 
产生原因是用了UINavigationController.
将UINavigationController的view作为subview添加到了其他viewController的view中。
或者把UINavigationController添加到UITabbarController中了。

此时,NavigationController的stack里面的viewController就收不到-(void)viewWillAppear:(BOOL)animated;等4个方法的调用。

原因还不敢确定,应该是这样的结构破坏了消息的响应链。导航控制器上层的viewController只是接受了导航控制器的view,而不是controller. 估计tabbarController内部也是处理了set进去的controller的view。

网上找了一些解决办法,但是有些只解决了Appear的方法调用,没有解决DisAppear的调用,最终找到了最好的一个解决办法,完美解决了Appear和DisAppear的调用。

首先要实现一个UITabBarController的子类。并且实现UINavigationControllerDelegate

C代码   收藏代码
  1. - (void)viewDidLoad  
  2. {  
  3.     FirstViewController *firstViewController = [[FirstViewController alloc]init];  
  4.     SecondViewController *secondViewController = [[SecondViewController alloc]init];  
  5.     ThirdViewController *thirdViewController = [[ThirdViewController alloc]init];  
  6.     FourthViewController *fourthViewController = [[FourthViewController alloc]init];  
  7.     FifthViewController *fifthViewController = [[FifthViewController alloc]init];  
  8.       
  9.     firstViewController.delegate = self;  
  10.     secondViewController.delegate = self;  
  11.     thirdViewController.delegate = self;  
  12.     fourthViewController.delegate = self;  
  13.     fifthViewController.delegate = self;  
  14.       
  15.     NSArray *viewControllerArray = [NSArray arrayWithObjects:firstViewController,secondViewController,thirdViewController,fourthViewController,fifthViewController,nil];   
  16.   
  17.     self.viewControllers = viewControllerArray;  
  18.     [self.view setFrame:CGRectMake(0, 0, 320, 460)];  
  19.       
  20.     [super viewDidLoad];  
  21.     // Do any additional setup after loading the view from its nib.  
  22. }  

以上FirstViewController到FifthViewController都是UINavigationController的子类。

将delegate指向self。

然后实现UINavigationControllerDelegate:

C代码   收藏代码
  1. - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated  
  2. {  
  3.     //每次当navigation中的界面切换,设为空。本次赋值只在程序初始化时执行一次  
  4.     static UIViewController *lastController = nil;  
  5.       
  6.     //若上个view不为空  
  7.     if (lastController != nil)   
  8.     {  
  9.         //若该实例实现了viewWillDisappear方法,则调用  
  10.         if ([lastController respondsToSelector:@selector(viewWillDisappear:)])   
  11.         {  
  12.             [lastController viewWillDisappear:animated];  
  13.         }  
  14.     }  
  15.       
  16.     //将当前要显示的view设置为lastController,在下次view切换调用本方法时,会执行viewWillDisappear  
  17.     lastController = viewController;  
  18.       
  19.     [viewController viewWillAppear:animated];  
  20. }  


这个方法是重点
C代码   收藏代码
  1. static UIViewController *lastController = nil;  

静态变量只在程序初始化的时候执行一次,也就是赋值为nil。
lastController指向的是新的界面要显示却还未显示的当前界面。
举例子来说 ,如果navigation当前显示的是A,现在要push到B。因此在push B之前,lastController指向的是A

C代码   收藏代码
  1. //若上个view不为空  
  2.     if (lastController != nil)   
  3.     {  
  4.         //若该实例实现了viewWillDisappear方法,则调用  
  5.         if ([lastController respondsToSelector:@selector(viewWillDisappear:)])   
  6.         {  
  7.             [lastController viewWillDisappear:animated];  
  8.         }  
  9.     }  

像上边说的,lastController这时为A,因此不为nil,将执行A的viewWillDisappear。

C代码   收藏代码
  1. lastController = viewController;  
  2.       
  3.  [viewController viewWillAppear:animated];  


在执行了A的viewWillDisappear之后,将lastController设为B(当前viewController),然后调用B的viewWillAppear。

本次方法执行结束了,如果navigation再push到C的时候,那么B的viewWillDisappear会执行,C的viewWillAppear会执行。这样就完美解决了viewWillAppear等4个方法不调用的问题。

如果想实现viewDidAppear和viewDidDisAppear方法,则只需按照同样道理,实现UINavigationControllerDelegate 的
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
方法就行了

你可能感兴趣的:(IOS)