父视图控制器如何被通知其子视图控制器已自行移除?

16

通过子视图控制器实现中的以下代码,可以删除子视图控制器:

- (void)commandFinishVC
{
    [ self.view removeFromSuperview];
    [ self removeFromParentViewController ];
}

子视图控制器及其视图已成功移除,但父级如何被通知呢?-viewDidDisappear未被调用,而-viewDidUnload已被弃用。

从我所找到的例子来看,总是假定父视图控制器是提名要删除子视图的事件的发起者,但(对我来说)子视图应该在其完成逻辑上是自主的。

应该通过利用self.parentViewController属性调用删除方法,并在父视图控制器中使用类似以下的内容吗?

- (void)commandFinishVC
{
    [ childVC.view removeFromSuperview];
    [ childVC removeFromParentViewController ];
}
1个回答

25
是的,你的父控制器通常应该控制子控制器的添加和删除,因此你的第二种方法似乎更适用。请参见UIViewController Class Reference中的Implementing a Container View Controller部分。
我怀疑你可以采用前一种方法,即子项自行删除,但苹果在他们的文档和关于Implementing UIViewController Containment的WWDC 2011会议上保持一致,容器控制器负责管理子项。
因此,回答你的问题,子项如何通知父项已被删除,没有建立的协议。但这并不奇怪,因为假定父项将启动此过程。而且,在子项需要启动此过程的范围内,文档建议父项具有公共API以管理子控制器。
所以,虽然没有关于孩子通知父母的协议,但是已经有发布的API可以让父控制器告诉子控制器它们已经被移动或删除了。具体来说,在父控制器移除子控制器时,它应该调用willMoveToParentViewController此文档明确表示我们必须执行此通知:

如果您正在实现自己的容器视图控制器,则必须在调用removeFromParentViewController方法之前调用子视图控制器的willMoveToParentViewController:方法...

因此,如视图控制器编程指南中的添加和删除子项部分所讨论的那样,在删除子项时,我们应该:
[childVC willMoveToParentViewController:nil];
[childVC.view removeFromSuperview];
[childVC removeFromParentViewController];

毫不意外,didMoveToParentViewController 的文档同样明确:当你添加一个子控制器时,在动画/转换(如果有)完成后,必须调用didMoveToParentViewController。我不知道如果我们不调用这两个通知方法会发生什么,但是苹果公司说我们必须这样做,因此这样做似乎是明智的。


这背后的原因是使用 VC(视图控制器)容器作为纯容器,没有视图属于它。子容器内的视图有它们关联的事件; 因此,子 VC 内的操作(例如,按下完成按钮)确定了释放子 VC。 - Roddy
非常感谢您的回复,它真的有助于澄清我一直在阅读的内容。 - Roddy
Rob,你知道如果你没有在子视图控制器中重写willMoveToParentViewController:方法,那么是否实际上需要调用它吗?苹果的文档让人觉得你应该调用这个方法,但我无法弄清楚如果你不在子视图控制器中重写它,它是否真的有任何作用。如果我不调用那个方法,我还没有看到任何问题。 - rdelmar
我非常确定其他苹果文档中指出,willMoveToParentViewController默认情况下不执行任何操作,但我无法再次找到它... 我也没有遇到任何因未调用它而引起的问题。 - Roddy
@rdelmar 我不知道如果你不调用这些方法会发生什么,但文档说我们“必须”这样做。(transitionFromViewControlleranimation块属于同一类别,被记录为“必需”,但在实践中通常不需要。)所以,简而言之,是的,你说得对,文档说我们必须调用这些方法,但在实践中是否如此并不清楚。就个人而言,如果文档说我们必须做某事(尤其是像单个方法调用这样简单的事情),我通常会按照良好、防御性编程的精神去做。 - Rob
@Roddy 我没有看到关于默认的 willMoveToParentViewController 什么都不做的参考资料,但在 WWDC 2011 会议上,他们甚至说如果你实现自己的 willMoveToParentViewController,那么你当然会调用 super 实现。你很可能是对的,即默认情况下什么也不做,但是由于我们“必须”调用它,并且如果我们有自己的实现,应该调用 super 方法的语言,我倾向于调用它。这只是一个调用,所以我认为几乎没有什么缺点。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接