UINavigationController:如何取消后退按钮事件?

时间:2011-02-25 08:34:37

标签: iphone ios uinavigationcontroller

在我的UIViewController我有一个UINavigationController,默认后退按钮。当用户单击后退按钮时,将显示一条警告消息:“你真的想回去吗?”。我知道,无法捕获后退按钮事件。只能使用viewWillDisappear并设置标志:

- (void)viewWillDisappear:(BOOL)animated {
    if (backBtnPressed) {
        UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Question" message:@"Do you really want to go back?" delegate:self cancelButtonTitle:@"No" otherButtonTitles: @"Yes", nil] autorelease];
        [alert show];   
    }
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    if (buttonIndex == 0) {
        // don't go back!
        // cancel the back button event
    }
    else if (buttonIndex == 1) {
        // go back
    }
}

但是这个代码我没有机会!我无法阻止后退按钮事件,不是吗?

我是否必须编写自己的后退按钮并将其设置为leftBarButtonItem?还是有人有个好主意吗? : - )

感谢您的帮助!

8 个答案:

答案 0 :(得分:52)

来自其他主题的answer符合此问题。所以我在这里重新发布:

我已实施UIViewController-BackButtonHandler扩展。它不需要子类化任何东西,只需将它放入您的项目并覆盖navigationShouldPopOnBackButton类中的UIViewController方法:

-(BOOL) navigationShouldPopOnBackButton {
    if(needsShowConfirmation) {
        // Show confirmation alert
        // ...
        return NO; // Ignore 'Back' button this time
    }
    return YES; // Process 'Back' button click and Pop view controller
}

Download sample app

答案 1 :(得分:13)

您需要做的是使用导航栏的代理,而不是导航控制器。

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPushItem:(UINavigationItem *)item; // called to push. return NO not to.
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item;    // called at end of animation of push or immediately if not animated
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;  // same as push methods
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;

答案 2 :(得分:9)

viewWillDisappear是视图将消失的事件的委托方法 - 开发人员无法做到这一点!如果可以,那将是viewShouldDisappear委托方法。

所以我猜你唯一的方法是使用自定义leftBarButtonItem

答案 3 :(得分:6)

我必须说这是苹果公司似乎并不容易做到的常见用例之一,我看到了很多努力试图让这个工作起来。我想也许我应该总结一下我的发现。

正如许多人所指出的,UINavigationBarDelegate中的以下方法是实现此功能的关键。

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;

许多人已经将UINavigationController子类化,并实施了上述方法,以便在不直接访问UINavigationBar的情况下轻松使用。

不幸的是,仍然存在一些问题。

  • 向后滑动手势不会调用此方法。
  • 虽然看起来有必要,但据报道在此方法中调用popViewControllerAnimated:崩溃。
  • 当取消弹出时,后退按钮保持灰色。

向后滑动手势

我们需要通过设置https://stackoverflow.com/a/23173035/2400328中的委托来拦截手势。

如果UINavigationController是子类,那将是:

self.interactivePopGestureRecognizer.delegate = self

并实施:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

修改委托属性时要小心,因为在调用初始化程序后它会被修改。

不调用popViewControllerAnimated:

虽然没有记录,但可以像https://stackoverflow.com/a/26084150/2400328中那样调用popViewControllerAnimated:

它涉及调用navigationBar:shouldPopItem:的{​​{1}}(来自子类)。

后退按钮

虽然这可能是一个小细节(特别是,如果你设计了自己的后退按钮),有一个简单的解决方案(由我编写:) https://stackoverflow.com/a/29440633/2400328

您只需要设置属性YES和NO。

UINavigationController

答案 4 :(得分:2)

您可以使用带图形的自定义按钮,它看起来与“后退”按钮完全相同,并使用此图形创建自定义leftBarButtonItem视图UIButton。使用自定义self选择器将目标back:添加到您的按钮,然后在此处弹出警报。如果用户按“是”退出关闭此视图控制器,如果不是 - 什么都不做。这里的技巧是按钮,它看起来与导航栏的后退按钮完全相同。

答案 5 :(得分:1)

如果您使用自己的后退按钮并使其成为导航控制器的左按钮,效果会更好。这绝对可以帮助你执行任何行动

答案 6 :(得分:1)

如果您正在寻找在iOS 10上使用Swift执行此操作的方法,则可以创建自定义UINavigationController,然后创建UINavigationBarDelegate扩展名:

class MyNavigationController : UINavigationController {

}
extension MyNavigationController : UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        return false
    }
}

答案 7 :(得分:0)

方法

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;

正在做你想做的事。不幸的是,我们不应该将UINavigationBar委托给我们自己的对象:(

Apple Documentation州:

  

...此外,导航控制器对象会自动将其自身指定为其UINavigationBar对象的委托,并防止其他对象更改该关系。 ...

一/该?做你想做的事就是把你自己的后退按钮放进去。 在该方法中,您进行测试并调用

[self.navigationController popViewControllerAnimated:true];

如果允许用户返回。