2015 年 4 月 30 日更新
根据 phatmann 的反馈(下面的第一条评论),我很好奇自从我一年多前回答这个问题以来是否发生了变化。我整理了一个简单的示例应用程序,并得到了一些有趣的结果。
选项 1,示例
https://github.com/greymouser/TestNVC
我没有能力轻松测试 8.x 之前的版本,所以我不确定从那以后是否发生了变化。但是,我最初描述的行为仍然会发生。 然而,由于将测试应用程序放在一起,我确实注意到了一个我以前没有注意到的奇怪之处。
如果我只依赖{will,did}MoveToParentViewController,我注意到在rootVC 上推送第一个非rootVC 时有一个虚假的didMoveToParentViewController: 调用,其父级为!= nil(暗示它已添加,未删除)。在我最初回答的时候我没有遇到这种情况,因为我的 NVC 上通常有“永久”rootVC,并且没有在那里实现回调。请参阅将日志记录设置为 LOG_WILL_DID_MTPVC 的示例应用程序(在 ViewController.m 中)。这是我所见内容的 -- 为空间编辑 -- 快照:
TestNVC[] -[vc(rootVC) willMoveToParentViewController [entering]
TestNVC[] -[vc(rootVC) didMoveToParentViewController [entering]
TestNVC[] -[vc(1) willMoveToParentViewController [entering]
TestNVC[] -[vc(rootVC) didMoveToParentViewController [entering] # <-- this is odd
TestNVC[] -[vc(1) didMoveToParentViewController [entering]
...
我最初的回答建议单独使用{will,did}MoveToParentViewController,因为它是处理这种行为的“一站式商店”。然而,既然我已经看到了对 rootVC 的虚假调用,我建议混合使用 {will,did}MoveToParentViewController 以及标准的 UINavigationControllerDelegate 回调。对于示例应用程序中的此行为,请将日志记录设置为 LOG_WILL_DID_MTPVC_LEAVING_AND_NVC_WILL_DID_SHOW_VC。现在我们看到以下内容:
TestNVC[] -[nvcD willShowViewController]: rootVC
TestNVC[] -[nvcD didShowViewController]: rootVC
TestNVC[] -[nvcD willShowViewController]: 1
TestNVC[] -[nvcD didShowViewController]: 1
TestNVC[] -[nvcD willShowViewController]: 2
TestNVC[] -[nvcD didShowViewController]: 2
TestNVC[] -[vc(2) willMoveToParentViewController [leaving]
TestNVC[] -[nvcD willShowViewController]: 1
TestNVC[] -[vc(2) didMoveToParentViewController [leaving]
TestNVC[] -[nvcD didShowViewController]: 1
TestNVC[] -[vc(1) willMoveToParentViewController [leaving]
TestNVC[] -[nvcD willShowViewController]: rootVC
TestNVC[] -[vc(1) didMoveToParentViewController [leaving]
TestNVC[] -[nvcD didShowViewController]: rootVC
...现在这更有意义了。
选项 2
我没有探索的另一个选项是使用您的 NVC 子类,覆盖 - pushViewController:animated: 和 - popViewControllerAnimated:,并将您想要的任何行为应用于被推送的 VC 或从 pop 返回的 VC。 (如果您尝试这样做,请务必记住在您的覆盖中调用 super。)
更新摘要
所以,感谢 phatmann 有机会重新解决这个问题。我认为我的回答现在更多是正确的。但是,我不太确定它是否“完全不真实”。 ;-)
原创
如果您描述的确切行为是您正在寻找的,则在您的子视图控制器上覆盖以下内容:
- (void)willMoveToParentViewController:(UIViewController *)parent;
- (void)didMoveToParentViewController:(UIViewController *)parent;
willMoveToParentViewController: 将在进入时使用 parent != nil 调用,在离开时使用 parent == nil 调用。 didMoveToParentViewController: 总是有父级!= nil。
有时,viewDidDisappear 可能有意义。但是,如果您真的要从父容器视图控制器中寻找 push 和 pop,那么上面的这些方法就是您想要的。