objective-c 检查 UIViewController 是否即将从导航堆栈中弹出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/642312/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Checking if a UIViewController is about to get Popped from a navigation stack?
提问by Jasarien
I need to know when my view controller is about to get popped from a nav stack so I can perform an action.
我需要知道我的视图控制器何时将从导航堆栈中弹出,以便我可以执行操作。
I can't use -viewWillDisappear, because that gets called when the view controller is moved off screen for ANY reason (like a new view controller being pushed on top).
我不能使用 -viewWillDisappear,因为当视图控制器出于任何原因移出屏幕时会被调用(比如一个新的视图控制器被推到顶部)。
I specifically need to know when the controller is about to be popped itself.
我特别需要知道控制器何时会弹出。
Any ideas would be awesome, thanks in advance.
任何想法都会很棒,提前致谢。
采纳答案by Tom Elliott
I don't think there is an explicit message for this, but you could subclass the UINavigationController and override - popViewControllerAnimated (although I haven't tried this before myself).
我不认为对此有明确的消息,但是您可以将 UINavigationController 子类化并覆盖 - popViewControllerAnimated(尽管我自己之前没有尝试过)。
Alternatively, if there are no other references to the view controller, could you add to its - dealloc?
或者,如果没有其他对视图控制器的引用,您可以添加到它的 - dealloc 中吗?
回答by Jeff Marino
Override the viewWillDisappearmethod in the presented VC, then check the isMovingFromParentViewControllerflag within the override and do specific logic. In my case I'm hiding the navigation controllers toolbar. Still requires that your presented VC understand that it was pushed though so not perfect.
覆盖viewWillDisappear呈现的 VC 中的方法,然后检查isMovingFromParentViewController覆盖中的标志并执行特定逻辑。就我而言,我隐藏了导航控制器工具栏。仍然需要您提供的 VC 了解它虽然并不完美但被推动。
回答by ma11hew28
Try overriding willMoveToParentViewController:(instead of viewWillDisappear:) in your custom subclass of UIViewController.
尝试在您的自定义子类中覆盖willMoveToParentViewController:(而不是viewWillDisappear:)UIViewController.
Called just before the view controller is added or removed from a container view controller.
在视图控制器添加或从容器视图控制器中删除之前调用。
- (void)willMoveToParentViewController:(UIViewController *)parent
{
[super willMoveToParentViewController:parent];
if (!parent) {
// `self` is about to get popped.
}
}
回答by caoimghgin
Fortunately, by the time the viewWillDisappear method is called, the viewController has already been removed from the stack, so we know the viewController is popping because it's no longer in the self.navigationController.viewControllers
幸运的是,在调用 viewWillDisappear 方法时,viewController 已经从堆栈中移除,所以我们知道 viewController 正在弹出,因为它不再在self.navigationController.viewControllers 中
Swift 4
斯威夫特 4
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let nav = self.navigationController {
let isPopping = !nav.viewControllers.contains(self)
if isPopping {
// popping off nav
} else {
// on nav, not popping off (pushing past, being presented over, etc.)
}
} else {
// not on nav at all
}
}
Original Code
原始代码
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if ((self.navigationController) &&
(![self.navigationController.viewControllers containsObject:self])) {
NSLog(@"I've been popped!");
}
}
回答by Ronald Nepsund
This is working for me.
这对我有用。
- (void)viewDidDisappear:(BOOL)animated
{
if (self.parentViewController == nil) {
NSLog(@"viewDidDisappear doesn't have parent so it's been popped");
//release stuff here
} else {
NSLog(@"PersonViewController view just hidden");
}
}
回答by dieselmcfadden
You can catch it here.
你可以在这里抓住它。
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (viewController == YourAboutToAppearController) {
// do something
}
}
This will fire just before the display of the new View. Nobody's moved yet. I use all the time to do magic in front of the asinine NavigationController. You can set titles and button titles and do whatever there.
这将在新视图显示之前触发。还没有人动呢。我总是在 asinine NavigationController 面前施展魔法。您可以设置标题和按钮标题并在那里执行任何操作。
回答by hiepnd
I have the same problem. I tried with viewDisDisappear, but I don't have the function get called :( (don't know why, maybe because all my VC is UITableViewController).
The suggestion of Alex works fine but it fails if your Navigation controller is displayed under the More tab. In this case, all VCs of your nav controllers have the navigationController as UIMoreNavigationController, not the navigation controller you have subclassed, so you will not be notified by the nav when a VC is about to popped.
Finaly, I solved the problem with a category of UINavigationController, just rewrite - (UIViewController *)popViewControllerAnimated:(BOOL)animated
我也有同样的问题。我尝试使用 viewDisDisappear,但我没有调用该函数:((不知道为什么,可能是因为我所有的 VC 都是 UITableViewController)。Alex 的建议工作正常,但如果您的导航控制器显示在More选项卡。在这种情况下,您的导航控制器的所有VC都将navigationController作为UIMoreNavigationController,而不是您子类化的导航控制器,因此当VC即将弹出时,导航不会通知您。
最后,我解决了问题使用 UINavigationController 的类别,只需重写 - (UIViewController *)popViewControllerAnimated:(BOOL)animated
- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
NSLog(@"UINavigationController(Magic)");
UIViewController *vc = self.topViewController;
if ([vc respondsToSelector:@selector(viewControllerWillBePopped)]) {
[vc performSelector:@selector(viewControllerWillBePopped)];
}
NSArray *vcs = self.viewControllers;
UIViewController *vcc = [vcs objectAtIndex:[vcs count] - 2];
[self popToViewController:vcc animated:YES];
return vcc;}
It works well for me :D
它对我很有效:D
回答by Oded Ben Dov
I tried this:
我试过这个:
- (void) viewWillDisappear:(BOOL)animated {
// If we are disappearing because we were removed from navigation stack
if (self.navigationController == nil) {
// YOUR CODE HERE
}
[super viewWillDisappear:animated];
}
The idea is that at popping, the view controller's navigationController is set to nil. So if the view was to disappear, and it longer has a navigationController, I concluded it was popped. (might not work in other scenarios).
这个想法是在弹出时,视图控制器的 navigationController 设置为 nil。所以如果视图要消失,并且它不再有导航控制器,我得出结论它被弹出。(在其他情况下可能不起作用)。
Can't vouch that viewWillDisappear will be called upon popping, as it is not mentioned in the docs. I tried it when the view was top view, and below top view - and it worked in both.
不能保证在弹出时会调用 viewWillDisappear,因为文档中没有提到它。我在视图是顶视图和顶视图下方时尝试了它 - 它在两者中都有效。
Good luck, Oded.
祝你好运,奥德。
回答by Orkhan Alikhanov
Subclass UINavigationControllerand override popViewController:
子类UINavigationController和覆盖popViewController:
Swift 3
斯威夫特 3
protocol CanPreventPopProtocol {
func shouldBePopped() -> Bool
}
class MyNavigationController: UINavigationController {
override func popViewController(animated: Bool) -> UIViewController? {
let viewController = self.topViewController
if let canPreventPop = viewController as? CanPreventPopProtocol {
if !canPreventPop.shouldBePopped() {
return nil
}
}
return super.popViewController(animated: animated)
}
//important to prevent UI thread from freezing
//
//if popViewController is called by gesture recognizer and prevented by returning nil
//UI will freeze after calling super.popViewController
//so that, in order to solve the problem we should not return nil from popViewController
//we interrupt the call made by gesture recognizer to popViewController through
//returning false on gestureRecognizerShouldBegin
//
//tested on iOS 9.3.2 not others
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let viewController = self.topViewController
if let canPreventPop = viewController as? CanPreventPopProtocol {
if !canPreventPop.shouldBePopped() {
return false
}
}
return true
}
}
回答by itechnician
You can use this one:
你可以使用这个:
if(self.isMovingToParentViewController)
{
NSLog(@"Pushed");
}
else
{
NSLog(@"Popped");
}

