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

Man*_*nni 17 iphone uinavigationcontroller ios

在我的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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢你的帮助!

one*_*ray 53

我从另一个主题回答这个问题.所以我在这里重新发布:

我已经实现了UIViewController-BackButtonHandler扩展.它不需要子类化任何东西,只需将它放入您的项目并navigationShouldPopOnBackButtonUIViewController类中重写方法:

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

下载示例应用.

  • 可悲的是,我们现在处于iOS 8,并且需要这个出色的代码来拦截Back按钮动作.优秀的解决方案,对Apple没有提供开箱即用的功能感到羞耻. (8认同)
  • 这个扩展与Swift 4完美配合.非常感谢你.[这里是快速3版本的扩展](https://gist.github.com/HamGuy/a099058e674b573ffe433132f7b5651e),如果有人需要 (3认同)

Enz*_*ran 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;
Run Code Online (Sandbox Code Playgroud)

  • 我的导航栏由导航控制器管理,并且手动将栏的代表设置为我的视图控制器导致例外,如果栏由导航控制器管理,则不允许解释在导航栏上手动设置委托. (7认同)

Jam*_*ord 9

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

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


tec*_*iao 7

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

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

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
Run Code Online (Sandbox Code Playgroud)

许多人已经子类化UINavigationController并实现了上述方法,使其易于使用而无需直接访问UINavigationBar.

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

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

向后滑动手势

我们需要通过设置代理来拦截手势,如/sf/answers/1622112481/中所述.

如果UINavigationController是子类,那将是:

self.interactivePopGestureRecognizer.delegate = self
Run Code Online (Sandbox Code Playgroud)

并实施:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
Run Code Online (Sandbox Code Playgroud)

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

不打电话 popViewControllerAnimated:

虽然没有记录,但popViewControllerAnimated:可以像/sf/answers/1825890531/中那样避免呼叫.

它涉及呼叫navigationBar:shouldPopItem:UINavigationController(从子类).

后退按钮

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

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

auto item = navigationBar.topItem;
item.hidesBackButton = YES;
item.hidesBackButton = NO;
Run Code Online (Sandbox Code Playgroud)