尝试处理 iOS 中的“后退”导航按钮操作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18824186/
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
Trying to handle "back" navigation button action in iOS
提问by AppsDev
I need to detect when the user taps the "back" button on the navigation bar, in order to perform some operations when that occurs. I'm trying to set manually an action to such button, this way:
我需要检测用户何时点击导航栏上的“后退”按钮,以便在发生这种情况时执行一些操作。我正在尝试手动设置对此类按钮的操作,如下所示:
[self.navigationItem.backBarButtonItem setAction:@selector(performBackNavigation:)];
- (void)performBackNavigation:(id)sender
{
// Do operations
[self.navigationController popViewControllerAnimated:NO];
}
I firstly placed that code in the view controller itself, but I found that self.navigationItem.backBarButtonItem
seemed to be nil
, so I moved that same code to the parent view controller, which pushes the former to the navigation stack. But I'm neither able to make it work. I've read some posts regarding this issue, and some of them said that the selector needs to be set at the parent view controller, but for me it doesn't work anyway... What could I'm doing wrong?
我首先将该代码放在视图控制器本身中,但我发现它self.navigationItem.backBarButtonItem
似乎是nil
,所以我将相同的代码移动到父视图控制器,将前者推送到导航堆栈。但我既不能让它发挥作用。我读过一些关于这个问题的帖子,其中一些人说需要在父视图控制器上设置选择器,但对我来说它无论如何都不起作用......我做错了什么?
Thanks
谢谢
回答by Kumar KL
Try this code using VIewWillDisappear
method to detect the press of The back button of NavigationItem:
试试这个代码使用VIewWillDisappear
方法来检测 NavigationItem 的后退按钮的按下:
-(void) viewWillDisappear:(BOOL)animated
{
if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
{
// Navigation button was pressed. Do some stuff
[self.navigationController popViewControllerAnimated:NO];
}
[super viewWillDisappear:animated];
}
OR There is another way to get Action of the Navigation BAck button.
或者还有另一种方法可以获取导航返回按钮的操作。
Create Custom button for UINavigationItem of back button .
为后退按钮的 UINavigationItem 创建自定义按钮。
For Ex:
例如:
In ViewDidLoad :
在 ViewDidLoad 中:
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:@"Home" style:UIBarButtonItemStyleBordered target:self action:@selector(home:)];
self.navigationItem.leftBarButtonItem=newBackButton;
}
-(void)home:(UIBarButtonItem *)sender
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
Swift :
斯威夫特:
override func willMoveToParentViewController(parent: UIViewController?)
{
if parent == nil
{
// Back btn Event handler
}
}
回答by dadachi
Swift
迅速
override func didMoveToParentViewController(parent: UIViewController?) {
if parent == nil {
//"Back pressed"
}
}
回答by Firula
Perhaps this answers doesn't fit your explanation but question title. It's useful when you are trying to know when you tapped the back button on an UINavigationBar
.
也许这个答案不符合您的解释,而是问题标题。当您想知道何时点击了UINavigationBar
.
In this case you can use UINavigationBarDelegate
protocol and implement one of this methods:
在这种情况下,您可以使用UINavigationBarDelegate
协议并实现以下方法之一:
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item;
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item;
When didPopItem
method is called, it's because you either tapped the back button or you used [UINavigationBar popNavigationItemAnimated:]
method and the navigation bar did pop the item.
当didPopItem
方法被调用,那是因为你要么挖后退按钮,或者你使用[UINavigationBar popNavigationItemAnimated:]
方法和导航栏确实流行的项目。
Now, if you want to know what action triggered the didPopItem
method you can use a flag.
现在,如果您想知道是什么操作触发了该didPopItem
方法,您可以使用一个标志。
With this approach I don't need to manually add a left bar button item with an arrow image in order to make it similar to iOS back button, and be able to set my custom target/action.
使用这种方法,我不需要手动添加带有箭头图像的左栏按钮项,以使其类似于 iOS 后退按钮,并且能够设置我的自定义目标/操作。
Let's see an example:
让我们看一个例子:
I have a view controller that has a page view controller, and a custom page indicator view. I'm also using a custom UINavigationBar to display a title to know on what page am I and the back button to go back to the previous page. And I also can swipe to previous/next page on page controller.
我有一个视图控制器,它有一个页面视图控制器和一个自定义页面指示器视图。我还使用自定义 UINavigationBar 显示标题以了解我在哪个页面上,并使用后退按钮返回上一页。而且我还可以在页面控制器上滑动到上一页/下一页。
#pragma mark - UIPageViewController Delegate Methods
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
if( completed ) {
//...
if( currentIndex > lastIndex ) {
UINavigationItem *navigationItem = [[UINavigationItem alloc] initWithTitle:@"Some page title"];
[[_someViewController navigationBar] pushNavigationItem:navigationItem animated:YES];
[[_someViewController pageControl] setCurrentPage:currentIndex];
} else {
_autoPop = YES; //We pop the item automatically from code.
[[_someViewController navigationBar] popNavigationItemAnimated:YES];
[[_someViewController pageControl] setCurrentPage:currentIndex];
}
}
}
So then I implement UINavigationBar delegate methods:
那么我实现 UINavigationBar 委托方法:
#pragma mark - UINavigationBar Delegate Methods
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
if( !_autoPop ) {
//Pop by back button tap
} else {
//Pop from code
}
_autoPop = NO;
return YES;
}
In this case I used shouldPopItem
because the pop is animated and I wanted to handle the back button immediately and not to wait until transition is finished.
在这种情况下,我使用了shouldPopItem
因为 pop 是动画的,我想立即处理后退按钮而不是等到过渡完成。
回答by Nico
The problem with didMoveToParentViewController
it's that it gets called once the parent view is fully visible again so if you need to perform some tasks before that, it won't work.
didMoveToParentViewController
它的问题在于,一旦父视图再次完全可见,它就会被调用,因此如果您需要在此之前执行某些任务,它将无法工作。
And it doesn't work with the driven animation gesture.
Using willMoveToParentViewController
works better.
它不适用于驱动动画手势。使用willMoveToParentViewController
效果更好。
Objective-c
目标-c
- (void)willMoveToParentViewController:(UIViewController *)parent{
if (parent == NULL) {
// ...
}
}
Swift
迅速
override func willMoveToParentViewController(parent: UIViewController?) {
if parent == nil {
// ...
}
}
回答by Ashish Kakkad
回答by Jeffrey Sun
Set the UINavigationBar's delegate, and then use:
设置 UINavigationBar 的委托,然后使用:
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
//handle the action here
}
回答by mark
Set the UINavigationControllerDelegate and implement this delegate func (Swift):
设置 UINavigationControllerDelegate 并实现这个委托 func (Swift):
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if viewController is <target class> {
//if the only way to get back - back button was pressed
}
}
回答by Shady
None of the other solutions worked for me, but this does:
其他解决方案都不适合我,但这确实适用:
Create your own subclass of UINavigationController, make it implement the UINavigationBarDelegate (no need to manually set the navigation bar's delegate), add a UIViewController extension that defines a method to be called on a back button press, and then implement this method in your UINavigationController subclass:
创建你自己的 UINavigationController 子类,让它实现 UINavigationBarDelegate(不需要手动设置导航栏的委托),添加一个 UIViewController 扩展来定义一个在按下后退按钮时调用的方法,然后在你的 UINavigationController 子类中实现这个方法:
func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
self.topViewController?.methodToBeCalledOnBackButtonPress()
self.popViewController(animated: true)
return true
}
回答by iMichele
In Swift 4 or above:
在 Swift 4 或更高版本中:
override func didMove(toParent parent: UIViewController?) {
if parent == nil {
//"Back pressed"
}
}
回答by Rivera
Use a custom UINavigationController
subclass, which implements the shouldPop
method.
使用UINavigationController
实现该shouldPop
方法的自定义子类。
In Swift:
在斯威夫特:
class NavigationController: UINavigationController, UINavigationBarDelegate
{
var shouldPopHandler: (() -> Bool)?
func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool
{
if let shouldPopHandler = self.shouldPopHandler, !shouldPopHandler()
{
return false
}
self.popViewController(animated: true) // Needed!
return true
}
}
When set, your shouldPopHandler()
will be called to decide whether the controller will be pop or not. When not set it will just get popped as usual.
设置后,您shouldPopHandler()
将被调用来决定控制器是否弹出。如果未设置,它将像往常一样弹出。
It is a good idea to disable UINavigationController
s interactivePopGestureRecognizer
as the gesture won't call your handler otherwise.
禁用UINavigationController
s是个好主意,interactivePopGestureRecognizer
否则手势不会调用您的处理程序。