addChildViewController--控制器包控制器解耦

3,774 阅读2分钟

1.相关属性和方法

@property(nonatomic,readonly) NSArray *childViewControllers
- (void)addChildViewController:(UIViewController *)childController;
- (void)removeFromParentViewController;
- (void)transitionFromViewController::::::;
- (void)willMoveToParentViewController:(UIViewController *)parent
- (void)didMoveToParentViewController:(UIViewController *)parent

2.关于willMoveToParentViewController方法和didMoveToParentViewController方法的使用

这两个方法用在子试图控制器交换的时候调用!即调用transitionFromViewController 方法时,调用。

当调用willMoveToParentViewController方法或didMoveToParentViewController方法时,要注意他们的参数使用:

  • 当某个子视图控制器将从父视图控制器中删除时,parent参数为nil。 即:[将被删除的子试图控制器 willMoveToParentViewController:nil];
  • 当某个子试图控制器将加入到父视图控制器时,parent参数为父视图控制器。 即:[将被加入的子视图控制器 didMoveToParentViewController:父视图控制器];

3.无需调用[childVc willMoveToParentViewController:parent]方法。

因为我们调用[parent addChildViewController:childVc]时,已经默认调用了。

只需要在transitionFromViewController方法后,调用[子视图控制器didMoveToParentViewController:父视图控制器];

4.无需调用[childVc didMoveToParentViewController:parent]方法。

因为我们调用[childVc removeFromParentViewController]时,已经默认调用了。

只需要在transitionFromViewController方法之前调用:[childVc willMoveToParentViewController:nil]。

5.范例

//在parent view controller 中添加 child view controller
FirstViewController *firstViewController=[[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
[self addChildViewController:firstViewController];

SecondViewController *secondViewController=[[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
[self addChildViewController:secondViewController];

ThirdViewController *thirdViewController=[[ThirdViewController alloc] initWithNibName:@"ThirdViewController" bundle:nil];
[self addChildViewController:thirdViewController];
thirdViewController.view.frame = self.view.bounds;
[self.view  addSubview:thirdViewController.view];

// addChildViewController会调用[child willMoveToParentViewController:self] ,但是不会调用didMoveToParentViewController,所以需要显示调用
[thirdViewController didMoveToParentViewController:self];
currentViewController=thirdViewController;

//切换child view controller
[self transitionFromViewController:currentViewController toViewController:firstViewController duration:4 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
            }  completion:^(BOOL finished) {
               //......
            }];
currentViewController=firstViewController;

//移除child view controller
//removeFromParentViewController在移除child前不会调用[self willMoveToParentViewController:nil] ,所以需要显示调用
[currentViewController willMoveToParentViewController:nil];
[currentViewController.view removeFromSuperview];
[currentViewController removeFromParentViewController];
  • 先 addChildViewController 后调用 addSubview,使子控制器的viewDidAppear 只被调用一次

  • 如果先调用 addSubview 后调用 addChildViewController,会产生两次子控制器 viewDidAppear 的调用

一次是来自 addChildViewController 后,视图跟随容器视图的生命周期方法被调用,另一次触发是来自 addSubview 的调用,并且时机是间于容器视图的 viewWillAppear 和 viewDidAppear 之间。 (猜测 addSubview 内部做了是否触发 viewWillAppear…等方法的判断)。 [参考来源: addChildViewController 与 addSubview 调用顺序](www.xiaobotalk.com/archives/47…

6.应用实例

根据标签切换页面应用实例链接:www.jianshu.com/p/913648c99…