检测导航栏上的“返回”按钮何时被按下

146

当导航栏的返回按钮(返回上一屏幕,返回父视图)被按下时,我需要执行一些操作。

有没有一些方法可以实现捕获事件并触发一些动作,在屏幕消失之前暂停并保存数据?


可能是在导航控制器中设置返回按钮操作的重复问题。 - nielsbot
1
请查看此线程中的解决方案 - Jiri Volejnik
我是这样做的在此展示决策 - Taras
18个回答

2

我使用了Pedro Magalhães的解决方案,但是当我像这样在扩展中使用它时,navigationBar:shouldPop没有被调用:

extension UINavigationController: UINavigationBarDelegate {
 public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
      return self.topViewController?.navigationShouldPopOnBackButton() ?? true
}

但是在一个UINavigationController子类中,相同的东西可以正常工作。

class NavigationController: UINavigationController, UINavigationBarDelegate {

func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
    return self.topViewController?.navigationShouldPopOnBackButton() ?? true
}

我看到一些其他的问题报告说这种方法没有被调用(但是其他委托方法按预期被调用),这是从iOS 13开始出现的吗? iOS 13 and UINavigationBarDelegate::shouldPop()

1

这种方法将视图控制器耦合在一起,所以我认为这不是一个好主意。 - undefined

1
正如Coli88所说,您应该检查UINavigationBarDelegate协议。
更一般地说,您还可以使用- (void)viewWillDisapear:(BOOL)animated来执行自定义工作,当当前可见视图控制器保留的视图即将消失时。不幸的是,这将涵盖推送和弹出两种情况。

1
purrrminator 所说,elitalon 的答案并不完全正确,因为即使通过编程方式弹出控制器,your stuff 也会被执行。
目前我找到的解决方案不是很好,但对我来说有效。除了 elitalon 提到的外,我还检查了是否正在进行编程式弹出:
- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];

  if ((self.isMovingFromParentViewController || self.isBeingDismissed)
      && !self.isPoppingProgrammatically) {
    // Do your stuff here
  }
}

在程序中编程弹出前,您需要将该属性添加到控制器并将其设置为“YES”:

self.isPoppingProgrammatically = YES;
[self.navigationController popViewControllerAnimated:YES];

感谢您的帮助!

1
我已经通过在导航栏左侧添加UIControl来解决了这个问题。
UIControl *leftBarItemControl = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, 90, 44)];
[leftBarItemControl addTarget:self action:@selector(onLeftItemClick:) forControlEvents:UIControlEventTouchUpInside];
self.leftItemControl = leftBarItemControl;
[self.navigationController.navigationBar addSubview:leftBarItemControl];
[self.navigationController.navigationBar bringSubviewToFront:leftBarItemControl];

当视图消失时,您需要记得将其移除:
- (void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if (self.leftItemControl) {
        [self.leftItemControl removeFromSuperview];
    }    
}

就这些!


1

7ynk3r的回答非常接近我最终使用的方法,但需要进行一些微调:

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

    UIViewController *topViewController = self.topViewController;
    BOOL wasBackButtonClicked = topViewController.navigationItem == item;

    if (wasBackButtonClicked) {
        if ([topViewController respondsToSelector:@selector(navBackButtonPressed)]) {
            // if user did press back on the view controller where you handle the navBackButtonPressed
            [topViewController performSelector:@selector(navBackButtonPressed)];
            return NO;
        } else {
            // if user did press back but you are not on the view controller that can handle the navBackButtonPressed
            [self popViewControllerAnimated:YES];
            return YES;
        }
    } else {
        // when you call popViewController programmatically you do not want to pop it twice
        return YES;
    }
}

0

self.navigationController.isMovingFromParentViewController在iOS8和9上不再起作用,我使用:

-(void) viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if (self.navigationController.topViewController != self)
    {
        // Is Popping
    }
}

-1

(SWIFT)

终于找到解决方案了...我们一直在寻找的方法是UINavigationController的代理方法"willShowViewController"

//IMPORT UINavigationControllerDelegate !!
class PushedController: UIViewController, UINavigationControllerDelegate {

    override func viewDidLoad() {
        //set delegate to current class (self)
        navigationController?.delegate = self
    }

    func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
        //MyViewController shoud be the name of your parent Class
        if var myViewController = viewController as? MyViewController {
            //YOUR STUFF
        }
    }
}

1
这种方法的问题在于它将 MyViewControllerPushedController 耦合在了一起。 - clozach

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接