检查UIViewController是否即将从导航堆栈中弹出?

时间:2009-03-13 11:46:32

标签: iphone objective-c uikit uiviewcontroller uinavigationbar

我需要知道我的视图控制器何时会从导航堆栈中弹出,以便我可以执行操作。

我不能使用-viewWillDisappear,因为当视图控制器由于任何原因(例如新的视图控制器被推到顶部)移出屏幕时会调用它。

我特别需要知道控制器即将自动弹出的时间。

任何想法都会很棒,提前谢谢。

15 个答案:

答案 0 :(得分:75)

覆盖显示的VC中的viewWillDisappear方法,然后检查覆盖中的isMovingFromParentViewController标志并执行特定逻辑。在我的情况下,我隐藏了导航控制器工具栏。仍然要求你所呈现的VC理解它被推动但不完美。

答案 1 :(得分:24)

尝试在viewWillDisappear:的自定义子类中覆盖willMoveToParentViewController:(而不是UIViewController)。

  

在容器视图控制器中添加或删除视图控制器之前调用。

- (void)willMoveToParentViewController:(UIViewController *)parent
{
    [super willMoveToParentViewController:parent];
    if (!parent) {
        // `self` is about to get popped.
    }
}

答案 2 :(得分:18)

幸运的是,在调用viewWillDisappear方法时,viewController已经从堆栈中删除了,所以我们知道viewController正在弹出,因为它不再位于 self.navigationController.viewControllers < / p>

Swift 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
    }
}

原始代码

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ((self.navigationController) && 
        (![self.navigationController.viewControllers containsObject:self])) {
        NSLog(@"I've been popped!");
    }
}

答案 3 :(得分:12)

这对我有用。

- (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");
    }
}

答案 4 :(得分:10)

我认为没有明确的消息,但你可以继承UINavigationController并覆盖 - popViewControllerAnimated(尽管我之前没有尝试过这个)。

或者,如果没有对视图控制器的其他引用,你可以添加到它的 - dealloc吗?

答案 5 :(得分:8)

你可以在这里抓住它。

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    if (viewController == YourAboutToAppearController) {
            // do something
    }
}

这将在显示新视图之前触发。没有人感动。我一直用asinine NavigationController做魔法。你可以设置标题和按钮标题,并在那里做任何事情。

答案 6 :(得分:3)

我有同样的问题。我尝试使用viewDisDisappear,但我没有调用函数:((不知道为什么,也许因为我所有的VC都是UITableViewController)。 Alex的建议工作正常,但如果您的导航控制器显示在更多选项卡下,则会失败。在这种情况下,导航控制器的所有VC都将navigationController作为UIMoreNavigationController,而不是您已经创建子类的导航控制器,因此当VC即将弹出时,导航器不会通知您。 最后,我解决了一个UINavigationController类的问题,只需重写 - (UIViewController *)popViewControllerAnimated:(BOOL)动画

- (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;}

对我来说效果很好:D

答案 7 :(得分:2)

我试过了:

- (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];
}

这个想法是在弹出时,视图控制器的navigationController被设置为nil。 因此,如果视图消失,并且它有更长的导航控制器,我总结它被弹出。 (可能在其他情况下不起作用)。

无法保证在弹出时会调用viewWillDisappear,因为文档中没有提到它。当视图是顶视图时,我尝试了它,并且在顶视图下方 - 它在两者中都有效。

祝你好运, 奥德。

答案 8 :(得分:1)

你可以使用这个:

if(self.isMovingToParentViewController)
{
    NSLog(@"Pushed");
}
else
{
    NSLog(@"Popped");
}

答案 9 :(得分:1)

子类.table-responsive并覆盖UINavigationController

Swift 3

popViewController

答案 10 :(得分:0)

也许您可以使用UINavigationBarDelegate的navigationBar:shouldPopItem协议方法。

答案 11 :(得分:0)

尝试在viewwilldisappear中进行此检查 if([self.navigationController.viewControllers indexOfObject:self] == NSNotFound){ //弹出这个视图已经发生了。 }

答案 12 :(得分:0)

有时我还需要防止突然弹出,所以对我来说最好的答案是Orkhan Alikhanov写的。但这没有用,因为未设置委托,所以我制作了最终版本:

import UIKit

class CustomActionsNavigationController: UINavigationController, 
                                         UIGestureRecognizerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        interactivePopGestureRecognizer?.delegate = self
    }

    override func popViewController(animated: Bool) -> UIViewController? {
        if let delegate = topViewController as? CustomActionsNavigationControllerDelegate {
            guard delegate.shouldPop() else { 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
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if let delegate = topViewController as? CustomActionsNavigationControllerDelegate {
            if !delegate.shouldPop() {
                return false
            }
        }

        // This if statement prevents navigation controller to pop when there is only one view controller
        if viewControllers.count == 1 {
            return false
        }

        return true
    }
}

protocol CustomActionsNavigationControllerDelegate {
    func shouldPop() -> Bool
}

更新

我添加了viewControllers.count == 1的大小写,因为如果堆栈中有一个控制器并且用户做出手势,它将冻结应用程序的UI。

答案 13 :(得分:0)

您可以看到通知:

- (void)viewDidLoad{
    [super viewDidLoad];
    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(navigationControllerWillShowViewController:) name:@"UINavigationControllerWillShowViewControllerNotification" object:nil];
}

- (void)navigationControllerDidShowViewController:(NSNotification *)notification{
    UIViewController *lastVisible = notification.userInfo[@"UINavigationControllerLastVisibleViewController"];
    if(lastVisible == self){
        // we are being popped
    }
}

答案 14 :(得分:0)

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    const BOOL removingFromParent = ![self.navigationController.viewControllers containsObject:self.parentViewController];
    if ( removingFromParent ) {
        // cleanup
    }
}