iOS早在iOS5的时候为了解耦、更加清晰的处理页面View的逻辑,UIViewController提供了addChildViewController方法,将ViewController作为容器处理视图控制器的切换,将比较复杂的UI使用子ViewController来管理。
iOS5.0之前只能在ViewController的view中不断的通过addSubView添加subView到VC的view视图层级中。这样使得主ViewController中的内容越来越混乱,代码越来越多,subView的管理越来越困难。
iOS5.0之后按照MVC的原则,每个ViewController只需要管理一个view视图层次结构,因此我们可以使用childViewController来拆分开发中比较复杂的View。并且此时的childViewController拥有了与父ViewController同步的声明周期。
项目中使用:
在我们项目的APP首页的实现中使用到了,首页内容展示位推荐分类菜单,以及每个菜单下的内容展示,不同的分类下的内容view
展示的UI多样化。
相关方法:
///子视图控制器数组
@property(nonatomic,readonly) NSArray *childViewControllers
///向父VC中添加子VC
- (void)addChildViewController:(UIViewController *)childController
///将子VC从父VC中移除
- (void) removeFromParentViewController
///fromViewController 当前显示在父视图控制器中的子视图控制器
///toViewController 将要显示的姿势图控制器
///duration 动画时间
/// options 动画效果(渐变,从下往上等等,具体查看API)
///animations 转换过程中得动画
///completion 转换完成
- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion
///当向父VC添加子VC之后,该方法会自动调用;
- (void)willMoveToParentViewController:(UIViewController *)parent
///从父VC移除子VC之后,该方法会自动调用
- (void)didMoveToParentViewController:(UIViewController *)parent
如何使用?:
如果在view上添加的只是简单的控件的话,那么使用addSubView添加到父ViewController上;
如果子视图是比较复杂的视图集合,功能丰富,就选择使用addChildViewController来添加新的子ViewController,但也需要通过addSubview将子ViewController的view添加到父视图的视图层级中;
iOS5之后使用addChildViewController时的原则,我们在使用addSubview的时候,同时调用addChildViewController方法将subView对应的viewController也加到当前viewController的管理中;
对于那些不需要显示的subView,只需通过addChildViewController把subVC添加到父控制器中,需要显示时再调用transitionFromViewController方法将其显示出来;
当收到系统的 Memory Warning 的时候,系统也会自动把当前没有显示的 subview 销毁掉 掉,以节省内存;
优点:
使页面逻辑更加清晰明了,遵循MVC模式,每个View对应相应的ViewController;
当存在不需显示的view时,将不会被加载,减少内尺使用;
当收到内存警告时,会将没有加载出的view率先释放,优化了程序的内存释放机制;
系统方法解释:
addChildViewController:
[A父视图控制器 addChildViewController:B子视图控制器]在视图控制器A中添加了子视图控制器B.调用这个方法时如果子视图控制器已经有父视图控制器了,那么调用该方法会先把子视图控制器从之前的父视图控制器中移除,然后再添加到当前的视图控制器上作为子视图控制器。
注意:调用addChildViewController后会自动调用willMoveToParentViewController:superVC方法;
removeFromParentViewController:
将子视图控制器从父视图控制器中移除,移除之后将自动调用didMoveToParentViewController
注意:调用removeFromParentViewControlle后会调用didMoveToParentViewController:nil方法
willMoveToParentViewController:
当一个视图控制器从视图控制器容器中被添加或者被删除之前,该方法被调用parent:父视图控制器,如果没有父视图控制器,将为nil;当调用removeFromParentViewController方法是必须先手动调用该方法,且parent参数为nil。
didMoveToParentViewController:
当从一个视图控制容器中添加或者移除viewController后,该方法被调用;当调用addChildViewController方法时必须手动调用该方法,且parent参数为父控制器。
代码展示:
添加子VC
//自动调用,可以省略
//[childVC willMoveToParentViewController: superVC];
[superVC addChildViewController:childVC];
[superVC.view addSubview:childVC.view];
[childVC didMoveToParentViewController:superVC];
- 删除子VC
[childVC willMoveToParentViewController];
[childVC removeFromParentViewController];
//自动调用,可以省略
//[childVC didMoveToParentViewController:nil];
- 切换子VC
[self addChildViewController:newController];
[self transitionFromViewController:oldController toViewController:newController duration:1.5f options:UIViewAnimationOptionCurveEaseOut animations:^{
} completion:^(BOOL finished) {
if (finished) {
[newController didMoveToParentViewController:self];
[oldController willMoveToParentViewController:nil];
[oldController removeFromParentViewController];
self.currentVC = newController;
}
else{
self.currentVC = oldController;
}
}];
总结:
addChildViewController向父视图控制器中添加子视图控制器时,添加之后自动调用willMoveToParentViewController,需要手动调用didMoveToParentViewController;
removeFromParentViewController将子视图控制器从父视图控制器中移除,移除之后自动调用didMoveToParentViewController: nil参数为nil,需要在移除前手动调用willMoveToParentViewController;
transitionFromViewController:toViewController在调用这个方法之前先调用[fromViewController willMoveToParentViewController:nil]然后在completion后调用[toViewController didMoveToParentViewController:self]方法;
在切换子视图控制器显示的时候需要保证切换的子视图控制器已经被添加到父视图控制器中;
当某个子视图控制器将从父视图控制器中删除时,parent参数为nil,即:[将被删除的VC willMoveToParentViewController:nil];
当某个子试图控制器将加入到父视图控制器时,parent参数为父视图控制器,即:[将被加入的VC didMoveToParentViewController:superVC];