iOS 5中的View Controller Containment如何工作?


108

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

我看了几次例子。有许多与此模式相关的方法,但是要准确地找出它们有些困难。我将在这里发布我的想法,看看社区是否会证实或怀疑我的怀疑。

方案1:从无父视图移到新的父视图控制器

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

前两行是否必须按照给定的顺序出现,或者可以颠倒吗?

方案2:从父视图控制器移动到无父视图控制器

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];

也有必要打电话[vc didMoveToParentViewController:nil]吗?在这种情况下,Session 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];

问题

我的主要问题是:通常,这是视图控制器包含区的工作方式吗?上面给出的机制正确吗?

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

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

Answers:


72

UIViewController文档很清楚何时以及何时不调用willMove/ didMove方法。查阅“实施Container View Controller”文档。

文档说,如果不重写addChildViewController,则不必调用 willMoveToParentViewController:method。但是,您确实需要didMoveToParentViewController:在转换完成后调用该方法。“同样,容器视图控制器有责任在调用willMoveToParentViewController:方法之前先调用该removeFromParentViewController方法。该removeFromParentViewController方法将调用didMoveToParentViewController:子视图控制器的方法。”

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

祝好运


17
我明白了,所以addChildViewController应该是平衡的didMoveToParentViewController,并willMoveToParentViewController应保持平衡removeFromParentViewController。这正是我想要的。不知道我怎么在文档中错过了它。
格雷戈里·希格利

为什么不?为什么您不必调用willMoveToParentViewController但必须调用didMoveToParentViewController?
user4951 '10 -10-10

因为这就是文档所说的。苹果显然感到我们不需要知道。

7
原因是为了动画的缘故:假设您正在创建自己的导航控制器。在幻灯片动画的开始,需要调用“ willMove”,在动画结束时,需要调用“ didMove”。现在,当您在动画开始时调用“ addChild”时,它将自动为您调用“ willMove”。但是它不知道动画(如果有的话)何时结束,因此您必须在动画结束时手动调用“ didMove”(或不使用动画立即调用)。
克里斯(Chris

2
对于“滑出”动画(例如,删除了孩子),您必须在动画开始时手动调用“ willMove”,因为uikit否则将不知道何时调用您的孩子VC的“ viewWillDisappear”。在动画的结尾,当您调用removeFromParentViewController时,它可以为您自动调用'didMove'。
克里斯

23

这部分不正确:

[vc willMoveToParentViewController:self];
[self addChildViewController:vc];
[self.view addSubview:vc.view]; // or something like this.
[vc didMoveToParentViewController:self];

根据文档:

当您的自定义容器调用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];

要删除视图控制器:

removeFromParentViewController方法删除子视图后,会自动调用子视图控制器的didMoveToParentViewController:方法。

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

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// [vc didMoveToParentViewController:nil] called automatically

看来,即使执行了其他操作,即使它看起来可行,也不会在presentedViewController上设置presentingViewController。
阿德里安

文档说didMoveToParentViewController “ 在调用addChildViewController:方法后立即调用”,它没有指定您实际添加子子视图的时间。我想知道是否每个人都错了。在某些Apple文档中是否有示例可以作为对照?
罗伯特·

注意:如果要移动的项目是具有覆盖的自定义类(除非您的覆盖在内部对其进行调用),您确实需要在致电willMoveToParentViewController之前addChildViewControlleraddChildViewController
2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.