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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5115135/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 19:01:07  来源:igfitidea点击:

UINavigationController: How to cancel the back button event?

iphoneiosuinavigationcontroller

提问by Manni

In my UIViewControllerI have a UINavigationControllerwith a default back button. When the user clicks the back button, a warning message should appear: "Do you really want to go back?". I know, that it is not possible to trap the back button event. It's only possible the use viewWillDisappearand set a flag:

在我的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
    }
}

But with this code I have no chance! I can't stop the back button event, isn't it?

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

Do I have to write my own back button and set it as leftBarButtonItem? Or is there anybody with a great idea? :-)

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

Thanks for your help!

谢谢你的帮助!

采纳答案by James Bedford

viewWillDisappearis a delegate method for the event that the view is going to disappear - and there's nothing the developer can do about that! If you could, it would be a viewShouldDisappeardelegate method.

viewWillDisappear是视图将要消失的事件的委托方法 - 开发人员对此无能为力!如果可以,这将是一个viewShouldDisappear委托方法。

So I guess the only way is as you suggest, to use a custom leftBarButtonItem.

所以我想唯一的方法就是按照你的建议,使用自定义leftBarButtonItem.

回答by onegray

My answerfrom another thread matches this question. So I repost it here:

我在另一个线程中的回答与这个问题相符。所以我在这里重新发布:

I've implemented UIViewController-BackButtonHandlerextension. It does not need to subclass anything, just put it into your project and override navigationShouldPopOnBackButtonmethod in UIViewControllerclass:

我已经实现了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.

下载示例应用程序

回答by Enzo Tran

What you need to do is to use the delegate of the navigation bar, and not the navigation controller.

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

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

回答by techniao

I must say this is one of the common use cases that Apple doesn't seem to make easy, and I see a lot of effort trying to get this working. I thought maybe I should summarize my findings here.

我必须说这是 Apple 似乎并不容易的常见用例之一,我看到了很多努力试图让它发挥作用。我想也许我应该在这里总结一下我的发现。

As many have pointed out, the method below in UINavigationBarDelegateis key to implementing this feature.

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

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

Many have subclassed UINavigationControllerand implemented the method above to make it easy to use without direct access to the UINavigationBar.

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

Unfortunately, there still remain some issues.

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

  • The swipe back gesture does not invoke this method.
  • Although it seems necessary, crashes are reported calling popViewControllerAnimated:in this method.
  • The Back button remains grayed out, when pop is cancelled.
  • 向后滑动手势不会调用此方法。
  • 尽管这似乎是必要的,但在调用popViewControllerAnimated:此方法时会报告崩溃。
  • 取消弹出时,后退按钮保持灰色。

Swipe back gesture

向后滑动手势

We need to intercept the gesture by setting the delegate as is done in https://stackoverflow.com/a/23173035/2400328.

我们需要通过设置代理来拦截手势,如https://stackoverflow.com/a/23173035/2400328 中所做的那样。

If the UINavigationControlleris subclassed, that would be:

如果UINavigationController是子类,那将是:

self.interactivePopGestureRecognizer.delegate = self

and implementing:

并实施:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

Take care in when you modify the delegate property, as it gets modified after the initializer is called.

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

Not calling popViewControllerAnimated:

不打电话 popViewControllerAnimated:

Although undocumented, calling popViewControllerAnimated:can be avoided as in https://stackoverflow.com/a/26084150/2400328.

虽然没有记录,但popViewControllerAnimated:可以避免调用,如https://stackoverflow.com/a/26084150/2400328

It involves calling navigationBar:shouldPopItem:of UINavigationController(from the subclass).

它需要调用navigationBar:shouldPopItem:UINavigationController(从子类)。

The Back button

后退按钮

Although this may be a minor detail (especially, if you have designed your own Back button), there is a simple solution (written by me :) https://stackoverflow.com/a/29440633/2400328

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

You only need to set a property YES and NO.

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

auto item = navigationBar.topItem;
item.hidesBackButton = YES;
item.hidesBackButton = NO;

回答by Nava Carmon

You can use a custom button with a graphics, which looks exactly like "Back" button and create a custom leftBarButtonItem view as UIButtonwith this graphics. Add target selfto your button with custom back:selector and pop your alert there. If the user presses "yes" to quit dismiss this view controller, if not - do nothing. The trick here is the button which looks exactly as navigation bar's back button.

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

回答by Max

If you're looking for a way to do this in Swift on iOS 10, you can create a custom UINavigationControllerand then a UINavigationBarDelegateextension:

如果您正在寻找一种在 iOS 10 上的 Swift 中执行此操作的方法,您可以先创建一个自定义UINavigationController,然后再创建一个UINavigationBarDelegate扩展:

class MyNavigationController : UINavigationController {

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

回答by visakh7

Its better if u make your own back button and make it the left button of the Navigation controller. That can definitely help u to perform any action

如果您制作自己的后退按钮并将其设为导航控制器的左侧按钮,那就更好了。这绝对可以帮助您执行任何操作

回答by Thorsten Niehues

The Method

方法

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

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

is doing what you want. Unfortunately we are not supposed to delegate UINavigationBar to our own objects :(

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

The Apple Documentationstates :

苹果文档的状态:

... In addition, a navigation controller object automatically assigns itself as the delegate of its UINavigationBar object and prevents other objects from changing that relationship. ...

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

One/The? way to do what you want is to put in your own back-button. In that Method you do your tests and call

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

[self.navigationController popViewControllerAnimated:true];

if the user is allowed to go back.

如果允许用户返回。