UIViewController新增了作为容器添加子容器的方法
/*
苹果官方注释
These two methods are public for container subclasses to call when transitioning between child
controllers. If they are overridden, the overrides should ensure to call the super. The parent argument in
both of these methods is nil when a child is being removed from its parent; otherwise it is equal to the new
parent view controller.
addChildViewController: will call [child willMoveToParentViewController:self] before adding the
child. However, it will not call didMoveToParentViewController:. It is expected that a container view
controller subclass will make this call after a transition to the new child has completed or, in the
case of no transition, immediately after the call to addChildViewController:. Similarly
removeFromParentViewController: does not call [self willMoveToParentViewController:nil] before removing the
child. This is also the responsibilty of the container subclass. Container subclasses will typically define
a method that transitions to a new child by first calling addChildViewController:, then executing a
transition which will add the new child's view into the view hierarchy of its parent, and finally will call
didMoveToParentViewController:. Similarly, subclasses will typically define a method that removes a child in
the reverse manner by first calling [child willMoveToParentViewController:nil].
*/
- (void)willMoveToParentViewController:(nullable UIViewController *)parent NS_AVAILABLE_IOS(5_0);
- (void)didMoveToParentViewController:(nullable UIViewController *)parent NS_AVAILABLE_IOS(5_0);
当在子视图控制器与父视图控制器与互相进行过渡的时候,子视图控制器可以调用这两个公开的方法。
如果重写了这两个方法,在重写的方法里面一定要调用父视图控制器的方法。
当子视图控制器从他们的父视图控制器中移除的时候,后面的parent参数都要填nil;否则,则要填新的父视图控制器。
当某个子视图控制器将从父视图控制器中删除时,parent参数为nil。
即:[将被删除的子试图控制器 willMoveToParentViewController:nil];
当某个子试图控制器将加入到父视图控制器时,parent参数为父视图控制器。
即:[将被加入的子视图控制器 didMoveToParentViewController:父视图控制器];
当调用
addChildViewController:
这个方法添加子视图控制器的时候,会自动调用[child willMoveToParentViewController:self]
方法;
然而,这时候并不会去调用didMoveToParentViewController:
方法;因此
- 一个容器的子视图控制器过渡到另一个子类控制器完成之后,会调用
didMoveToParentViewController:
方法 - 没有过渡到另一个子类控制器, 当调用
addChildViewController:
方法后会马上调用didMoveToParentViewController:
方法
- 相似的 用
removeFromParentViewController:
这个方法, 在移除子容器之前不会调用[self willMoveToParentViewController:nil]
方法
这也是父视图控制器的职责
父视图控制器应当定义一个方法用于过渡到一个新的子视图控制器, 方法里面要先调用
addChildViewController:
方法
然后执行过渡,执行完之后会将子视图控制器加到他的父视图控制器之中,然后最后会调用didMoveToParentViewController:
方法相似的,父视图控制器需要定义一个相反的方式--来移除子容器的方法,方法需要首先调用
[child willMoveToParentViewController:nil]
方法
以上是本人对这两个方法的官方注释的翻译, 下面结合这些注释谈谈这两个方法的使用
-
在iOS 5.0之前,只能在UIViewController的View中通过addSubView的方法来添加子view,而有一些View是不需要一直出现的,但是在ViewDidLoad之后,则会一起加载到内存中,影响性能的同时不方便管理。
-
在在iOS 5.0及以后,iOS为UIViewController类添加了新的属性和方法:
@property(nonatomic,readonly) NSArray *childViewControllers
- (void)addChildViewController:(UIViewController *)childController
- (void) removeFromParentViewController
- (void)transitionFromViewController::::::
- (void)willMoveToParentViewController:(UIViewController *)parent
- (void)didMoveToParentViewController:(UIViewController *)parent
这样,就能够将一个页面中的UIViewController控制起来,而不是混乱的共用一个UIViewController,最重要的是,编程习惯的革命:降低了功能的耦合度!
[父视图控制器 addChildViewController:子视图控制器];
在此,图控制器A添加了另一个图控制器B,那么A充当父视图控制器,B充当子视图控制器。父视图控制器充当了视图控制器容器的角色。
addChildViewController方法:
- (void)addChildViewController:(UIViewController *)childController
向视图控制器容器中添加子视图控制器
childController:子视图控制器
当要添加的子视图控制器已经包含在视图控制器容器中,那么,相当于先从父视图控制器中删除,然后重新添加到父视图控制器中。
removeFromParentViewController 方法
- (void)removeFromParentViewController
从父视图控制器中删除。
transitionFromViewController 方法
- (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
交换两个子视图控制器的位置(由于添加的顺序不同,所以子试图控制器在父视图控制器中存在层次关系)
fromViewController:
当前显示的子试图控制器,将被替换为非显示状态
toViewController:
将要显示的子视图控制器
duration:
交换动画持续的时间,单位秒
options:
动画的方式
animations:
动画Block
completion:
完成后执行的Block
willMoveToParentViewController
方法
- (void)willMoveToParentViewController:(UIViewController *)parent
当一个视图控制器从视图控制器容器中被添加或者被删除之前,该方法被调用
parent:
父视图控制器,如果没有父视图控制器,将为nil
注意点:
- 当我们向我们的视图控制器容器中调用
removeFromParentViewController
方法时,必须要先调用该方法,且parent
参数为nil
:
[将要删除的视图控制器 willMoveToParentViewController:nil];
- 当我们调用
addChildViewController
方法时,在添加子视图控制器之前将自动调用该方法。所以,就不需要我们显示调用了。
- 当从一个视图控制容器中添加或者移除
viewController
后,该方法被调用。
parent:
父视图控制器,如果没有父视图控制器,将为nil
//didMoveToParentViewController 方法
- (void)didMoveToParentViewController:(UIViewController *)parent
- 当我们向我们的视图控制器容器(就是父视图控制器,它调用
addChildViewController
方法加入子视图控制器,它就成为了视图控制器的容器)中添加(或者删除)子视图控制器后,必须调用该方法,告诉iOS,已经完成添加(或删除)子控制器的操作。 -
removeFromParentViewController
方法会自动调用了该方法,所以,删除子控制器后,不需要在显示的调用该方法了。
其实,这几个方法中的API说明,看的还懂。
最后,
关于willMoveToParentViewController
方法和didMoveToParentViewController
方法的使用
这两个方法用在子试图控制器交换的时候调用!即调用
transitionFromViewController
方法时,调用。当调用
willMoveToParentViewController
方法或didMoveToParentViewController
方法时,要注意他们的参数使用:
- 当某个子视图控制器将从父视图控制器中删除时,
parent
参数为nil
。
[将被删除的子试图控制器 willMoveToParentViewController:nil];
- 当某个子试图控制器将加入到父视图控制器时,
parent
参数为父视图控制器。
[将被加入的子视图控制器 didMoveToParentViewController:父视图控制器];
- 无需调用[子视图控制器
willMoveToParentViewController:
父视图控制器]方法。因为我们调用[父视图控制器 addChildViewController:子视图控制器]
时,已经默认调用了。
只需要在transitionFromViewController
方法后,调用
[子视图控制器didMoveToParentViewController:父视图控制器]
- 无需调用
[子视图控制器 didMoveToParentViewController:父视图控制器]
方法。因为我们调用
[子视图控制器 removeFromParentViewController]
时,已经默认调用了。
只需要在transitionFromViewController
方法之前调用:
[子视图控制器 willMoveToParentViewController:nil]