尝试处理 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

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

Trying to handle "back" navigation button action in iOS

iosuinavigationcontrolleruinavigationbarselector

提问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.backBarButtonItemseemed 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 VIewWillDisappearmethod 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 UINavigationBarDelegateprotocol and implement one of this methods:

在这种情况下,您可以使用UINavigationBarDelegate协议并实现以下方法之一:

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

When didPopItemmethod 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 didPopItemmethod 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 shouldPopItembecause 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 didMoveToParentViewControllerit'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 willMoveToParentViewControllerworks better.

它不适用于驱动动画手势。使用willMoveToParentViewController效果更好。

Objective-c

目标-c

- (void)willMoveToParentViewController:(UIViewController *)parent{
    if (parent == NULL) {
        // ...
    }
}

Swift

迅速

override func willMoveToParentViewController(parent: UIViewController?) {
    if parent == nil {
        // ...  
    }
}

回答by Ashish Kakkad

This is Objective-C version of dadachi'sAnswer :

这是dadachi的答案的Objective-C版本:

Objective-C

目标-C

- (void)didMoveToParentViewController:(UIViewController *)parent{
    if (parent == NULL) {
        NSLog(@"Back Pressed");
    }
}

回答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 UINavigationControllersubclass, which implements the shouldPopmethod.

使用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 UINavigationControllers interactivePopGestureRecognizeras the gesture won't call your handler otherwise.

禁用UINavigationControllers是个好主意,interactivePopGestureRecognizer否则手势不会调用您的处理程序。