当我从导航控制器弹出顶视图控制器时,我目前需要实现一些代码。有没有办法检测视图控制器何时从导航控制器堆栈弹出?
我想尽可能远离使用viewWillDisappear
或viewDidDisappear
,因为我在我的项目中使用了splitview
,并且在主视图中选择不同的行也将触发viewWillDisappear
/ viewDidDisappear
方法。
您可以使用视图控制器的isMovingFromParentViewController
属性检测是否正在弹出视图,如下所示:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isMovingFromParentViewController])
{
NSLog(@"View controller was popped");
}
else
{
NSLog(@"New view controller was pushed");
}
}
isMovingFromParentViewController
返回一个布尔值,指示视图控制器正在从其父级中删除。
更新20150430
基于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 sublcass,覆盖- pushViewController:animated:
和- popViewControllerAnimated:
,并将你想要的任何行为应用于被推送的VC,或者从pop返回的VC。 (如果您尝试这样做,请务必记住在覆盖中调用super
。)
更新摘要
所以,感谢phatmann有机会重新开始这个。我想我的答案现在更正确了。但是,我不太确定它是否“完全不真实”。 ;-)
原版的
如果您描述的确切行为是您要查找的内容,则在子视图控制器上覆盖以下内容:
- (void)willMoveToParentViewController:(UIViewController *)parent;
- (void)didMoveToParentViewController:(UIViewController *)parent;
输入时,willMoveToParentViewController:
将被父母调用!= nil,离开时父母== nil。 didMoveToParentViewController:
将永远有父!=无。
有时,viewDidDisappear
可能有意义。但是,如果您真正从父容器视图控制器中寻找推送和弹出,那么上述方法就是您想要的。
对于Swift用户(Swift 3 - 4.2):
我想检测视图控制器何时从堆栈弹出,所以我无法使用viewWillDisappear
或viewDidDisappear
回调,因为当视图控制器不再可见时将调用这些回调,而不是当它从弹出窗口中弹出时堆。
但您可以通过以下操作使用导航控制器Delegates UINavigationControllerDelegate
:
让你的控制器符合UINavigationControllerDelegate
:
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.delegate = self
}
}
extension ViewController : UINavigationControllerDelegate {
override func willMove(toParentViewController parent: UIViewController?) {
/*You can detect here when the viewcontroller is being popped*/
}
}
希望这有帮助,祝你好运
如果您在删除视图控制器之前不需要知道,并且只需要知道它已被弹出,您也可以使用deinit
。
class ViewController: UIViewController {
deinit {
// View controller has been popped/dismissed and it's being released
}
}
此方法适用于通知协调员或其他代理人。