项目当中当逻辑比较复杂时,我们经常用一个控制器包含其他一个或多个控制器,嵌套VC来进行使用,前者称为容器控制器 (Container View Controller),后者为子控制器 (Child View Controller)。UINavigationController、UITabBarController 就是常用的容器控制器。
之前项目里添加子vc只是添加了view,发现navigationController获取不到,生命周期(AppearanceMethods)的调用也是混乱的。发现调用addChildViewController才会把子控制器加入到容器控制器的层级中。
添加子控制器
[self addChildViewController:containerVC];
containerVC.view.frame=self.view.bounds;
[self.view addSubview:containerVC.view];
[containerVC didMoveToParentViewController:self];
移除子控制器
[containerVC willMoveToParentViewController:nil];
[containerVC.view removeFromSuperview];
[containerVC removeFromParentViewController];
这里注意willMoveToParentViewController/didMoveToParentViewController api的描述中
两个容器控制器间的切换
[self transitionFromViewController:containerVC toViewController:newVC duration:0.25 options:0 animations:^{
containerVC.view.frame = self.view.frame;
newVC.view.frame = self.view.frame;
}completion:^(BOOL finished) {
[containerVC removeFromParentViewController];
[newVC didMoveToParentViewController:self];
}];
在调用这个方法之前,要确保已经调用addChildViewController加入到容器控制器的层级中
该方法,执行完以后,fromViewController指代的视图控制器的View将从界面消失;
toViewController所指代的视图控制器的View将被载入到页面中。
beginAppearanceTransition/endAppearanceTransition
但是addChildViewController后,AppearanceMethods的调用问题并没有解决,在两个子控制器切换时,viewDidAppear/viewDidDisappear等并没有调用,苹果提供了api解决这个问题。
在容器控制器中重写shouldAutomaticallyForwardAppearanceMethods, return NO
-(BOOL)shouldAutomaticallyForwardAppearanceMethods{
return NO;
}
返回NO以后,系统将不再调用viewWillAppear: /viewDidAppear:/ viewWillDisappear:/viewDidDisappear:方法,而是通过beginAppearanceTransition/endAppearanceTransition主动调用
这两个函数的是成对出现的
[self beginAppearanceTransition:YES animated:animated];//调用viewWillAppear
[self endAppearanceTransition];//调用viewDidAppear
[self beginAppearanceTransition:NO animated:animated];//调用viewWillDisappear
[self endAppearanceTransition];//调用viewDidDisappear
在容器控制器里的viewWillAppear: /viewDidAppear:/ viewWillDisappear:/viewDidDisappear:和子控制器切换时进行对应的调用,就可以解决这个问题了
willMoveToParentViewController/didMoveToParentViewController方法还经常用于监听系统侧滑返回事件
因为UINavigationController也算一个容器控制器,push的时候调用willMoveToParentViewController/didMoveToParentViewController,pop的时候也会对应调用。
当侧滑返回时会先调用willMoveToParentViewController,页面完全消失后调用didMoveToParentViewController,如果想在侧滑页面完全消失后做操作,可重写didMoveToParentViewController方法