【问题标题】:How does View Controller Containment work in iOS 5?视图控制器包含在 iOS 5 中是如何工作的?
【发布时间】:2012-01-12 20:46:19
【问题描述】:

在 WWDC 2011 Session 102 中,Apple 引入了 View Controller Containment,这是一种创建自定义视图控制器容器的能力,类似于 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];

问题

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

在调用addChildViewController之前需要调用willMoveToParentViewController吗?这对我来说似乎是合乎逻辑的顺序,但这是绝对必要的吗?

是否需要在调用removeFromParentViewController之后再调用didMoveToParentViewController:nil

【问题讨论】:

    标签: ios uiviewcontroller ios5


    【解决方案1】:

    UIViewController 文档非常清楚何时以及何时不调用 willMove/didMove 方法。查看"Implementing a Container View Controller" 文档。

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

    另外,还有一个例子here和示例代码here

    祝你好运

    【讨论】:

    • 我明白了,所以addChildViewController 应该与didMoveToParentViewController 平衡,willMoveToParentViewController 应该与removeFromParentViewController 平衡。这正是我一直在寻找的。不知道我是如何在文档中错过它的。
    • 为什么不呢?为什么你不必调用 willMoveToParentViewController 而是调用 didMoveToParentViewController?
    • 因为这就是文档所说的。苹果显然觉得我们不需要知道。
    • 原因是为了动画:假设您正在创建自己的导航控制器。在滑入动画开始时,需要调用“willMove”,在动画结束时,需要调用“didMove”。现在,当您在动画开始时调用“addChild”时,它会自动为您调用“willMove”。但它无法知道动画(如果有的话)何时结束,因此您必须在动画结束时手动调用“didMove”(或在没有动画时立即调用)。
    • 对于'滑出'动画,例如孩子被移除,你必须在动画开始时手动调用'willMove',否则uikit不知道何时调用您的孩子 VC 的“viewWillDisappear”。并且在动画结束时,当你调用 removeFromParentViewController 时,它会自动为你调用 'didMove'。
    【解决方案2】:

    这部分不正确:

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

    According to the docs:

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

    For removing view controllers:

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

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

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

    【讨论】:

    • 看来,如果不这样做,即使它似乎工作,presentingViewController 也没有设置在presentedViewController 上。
    • 文档说调用 didMoveToParentViewController "立即 在调用 addChildViewController: 方法后",它没有指定您实际添加子子视图的时间。我想知道是不是每个人都搞错了。在某些 Apple Docs 中是否有我们可以检查的示例?
    • 注意:如果您要移动的项目是覆盖 addChildViewController 的自定义类(除非您的覆盖调用它在内部)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    相关资源
    最近更新 更多