本篇文章主要是关于以下几个方法的深度调研
- (void)willMoveToParentViewController:(nullable UIViewController *)parent
- (void)didMoveToParentViewController:(nullable UIViewController *)parent
- (void)addChildViewController:(UIViewController *)childController
- (void)removeFromParentViewController
willMoveToParentViewController: didMoveToParentViewController:
官方文档翻译
两个方法共同的翻译
这两个方法是公共的,供容器子类在child controllers之间转换时调用。
如果它们被覆盖,则覆盖应确保调用super。
parent参数,是父controller 当将孩子从其父母中删除时,参数是nil。
addChildViewController: 在添加child之前 , 会调用[child willMoveToParentViewController:self]。
但是,它不会调用didMoveToParentViewController:。
当一个容器的viewController 过渡到子controller完成会调用,或者没有过渡的时候会立刻调用
同样的 , removeFromParentViewController不会在删除child之前调用[self willMoveToParentViewController:nil]。
这也是容器子类的职责。容器子类通常会定义一个方法,通过第一次调用addChildViewController:去过渡到一个新的child,
在执行过渡的时候,也将添加孩子的视图到父视图的层次结构中,
最后将调用
didMoveToParentViewController :。
同样,子类通常会定义一个方法来删除一个child。通过调用[child willMoveToParentViewController:nil]进行相反的操作
在将视图控制器添加到容器视图控制器或从容器视图控制器中删除之前调用。
当视图控制器需要自己已被添加到容器时,可以重写此方法。
如果要实现自己的容器视图控制器,则必须在调用removeFromParentViewController之前,先调用子视图控制器的willMoveToParentViewController:方法,并传入父值参数为 nil。
当您的自定义容器调用addChildViewController:方法时,它自动调用添加的chilld 的 willMoveToParentViewController:方法
- (void)willMoveToParentViewController:(nullable UIViewController *)parent
在从容器视图控制器添加或删除视图控制器之后调用。
当要监听视图控制器要添加到容器中时,可以重写此方法。
如果要实现自己的容器视图控制器,则必须在子视图控制器完成转换之后调用,如果没有转换,在addChildViewController方法之后立即调用该方法
removeFromParentViewController方法会自动调用子视图控制器的didMoveToParentViewController:方法。
- (void)didMoveToParentViewController:(nullable UIViewController *)parent
addChildViewController: removeFromParentViewController
此方法在当前视图控制器和childController参数中的对象之间创建父子关系。
将子视图控制器的视图嵌入到当前视图控制器的内容中时,这种关系是必要的。
如果新的子视图控制器已经是容器视图控制器的子代,则在添加之前将其从该容器中删除。
此方法仅旨在由自定义容器视图控制器的实现调用。 如果重写此方法,则必须在实现中调用super。
- (void)addChildViewController:(UIViewController *)childController
从其父级中删除视图控制器。
此方法仅旨在由自定义容器视图控制器的实现调用。 如果重写此方法,则必须在实现中调用super。
- (void)removeFromParentViewController
总结
在经过实际的Demo验证后发现,
当使用导航控制器的时候, 会由导航控制器去调用相关方法:
A 页面 push 到B页面 时, 会调用B页面的willMoveToParentViewController:
didMoveToParentViewController:
方法 参数为A页面
B页面 pop 回A页面时,也会调用B页面的 willMoveToParentViewController:
didMoveToParentViewController:
方法, 参数为nil
当我们自己创建容器controller的时候
A.view addSubview:B.view
只会调用B页面的 viewWillAppear
和 viewDidAppear
方法
如果再加上一句 [ A addChildViewController:B];
会调用B页面的 willMoveToParentViewController:
,参数是A
如果我们手动调用didMoveToParentViewController,
这个方法会走两遍??
如果再加上一句 [C addChildViewController:B];
会再调用B页面的 willMoveToParentViewController: nil
didMoveToParentViewController:nil
和removeFromParentViewController
方法 再调用 willMoveToParentViewController: nil
removeFromParentViewController
[B removeFromParentViewController]
会调用两次 [B didMoveToParentViewController:nil]
网友评论