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
UINavigationController: How to cancel the back button event?
提问by Manni
In my UIViewController
I have a UINavigationController
with 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 viewWillDisappear
and 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
viewWillDisappear
is 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 viewShouldDisappear
delegate 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 navigationShouldPopOnBackButton
method in UIViewController
class:
我已经实现了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
}
回答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 UINavigationBarDelegate
is key to implementing this feature.
正如许多人指出的那样,下面的方法UINavigationBarDelegate
是实现此功能的关键。
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
Many have subclassed UINavigationController
and 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 UINavigationController
is 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 UIButton
with this graphics. Add target self
to 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 UINavigationController
and then a UINavigationBarDelegate
extension:
如果您正在寻找一种在 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.
如果允许用户返回。