View Controller Containment如何在iOS 5中运行?

Gre*_*ley 107 uiviewcontroller ios ios5

在2011年WWDC会话102,苹果推出视图控制器遏制,这是创建定制的视图控制器容器的能力,类似于UITabBarController,UINavigationController和类似物.

我多次看过这些例子.有一系列与这种模式相关的方法,但有点难以弄清楚它们.我将在这里发布我认为正在发生的事情,看看社区是否会确认或否定我的怀疑.

场景1:从无父节点移动到新的父视图控制器

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];
Run Code Online (Sandbox Code Playgroud)

前两行必须按给定的顺序发生,还是可以反转?

场景2:从父视图控制器移动到没有父视图控制器

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
Run Code Online (Sandbox Code Playgroud)

还有必要打电话[vc didMoveToParentViewController:nil]吗?会话102中的示例在这种情况下没有这样做,但我不知道这是否是遗漏.

场景3:从一个父视图控制器移动到另一个父视图控制器

这可能以下列方式发生,因为将封装每个父视图控制器中的逻辑.

// In the old parent
[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

// In the new parent
[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];
Run Code Online (Sandbox Code Playgroud)

问题

我的主要问题是:一般来说,视图控制器包含应该如何工作?上面给出的机制是否正确?

是否有必要在打电话willMoveToParentViewController前打电话addChildViewController?这对我来说似乎是合乎逻辑的顺序,但它是否是必要的?

打电话didMoveToParentViewController:nil后有必要打电话removeFromParentViewController吗?

tim*_*man 73

UIViewController关于何时何何不调用willMove/ didMove方法,文档非常明确.查看"实现容器视图控制器"文档.

文档说,如果你不覆盖addChildViewController,你不必调用 willMoveToParentViewController:方法.但是,您需要didMoveToParentViewController:在转换完成后调用该方法."同样,容器视图控制器负责在调用willMoveToParentViewController:方法之前调用该removeFromParentViewController方法.该removeFromParentViewController方法调用didMoveToParentViewController:子视图控制器的方法."

此外,还有制定了一个例子在这里和示例代码在这里.

祝好运

  • 我明白了,所以`addChildViewController`应与`didMoveToParentViewController`平衡,`willMoveToParentViewController`应与`removeFromParentViewController`平衡.这正是我所寻找的.不知道我在文档中是如何错过它的. (17认同)
  • 原因是出于动画的缘故:假设您正在创建自己的导航控制器.在滑入动画开始时,需要调用'willMove',并且在动画结束时,需要调用'didMove'.现在,当您在动画开始时调用"addChild"时,它会自动为您调用"willMove".但是它无法知道动画(如果有的话)何时结束,所以你必须在动画结束时手动调用'didMove'(或者立即没有动画). (7认同)
  • 至于"滑出"动画,例如孩子被移除,你必须在动画开始时手动调用'willMove',因为uikit否则不知道何时调用你的孩子VC的'viewWillDisappear'.在动画结束时,当你调用removeFromParentViewController时,它可以自动为你调用'didMove'. (2认同)

nev*_*ing 22

这部分不正确:

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];
Run Code Online (Sandbox Code Playgroud)

根据文件:

当您的自定义容器调用addChildViewController:方法时,它会自动调用视图控制器的willMoveToParentViewController:方法作为子项添加,然后再添加它.

所以你不需要[vc willMoveToParentViewController:self]电话.它会在您致电时自动完成[self addChildViewController:vc].这是代码示例:

[self addChildViewController:vc];
// [vc willMoveToParentViewController:self] called automatically
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];
Run Code Online (Sandbox Code Playgroud)

要删除视图控制器:

removeFromParentViewController方法在删除子视图后自动调用子视图控制器的didMoveToParentViewController:方法.

大概这个电话是[oldVC didMoveToParentViewController:nil].

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// [vc didMoveToParentViewController:nil] called automatically
Run Code Online (Sandbox Code Playgroud)