操作导航栏返回按钮

3

当用户点击后退按钮时,我希望显示一个确认弹窗。以下是我尝试添加该操作的方式:

self.navigationItem.hidesBackButton = true
let newBackButton = UIBarButtonItem(title: "<", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.save(sender:)))
self.navigationItem.leftBarButtonItem = newBackButton

这部分工作正常,但我想要默认的返回按钮图像而不是自定义标题。如何实现?
我也尝试了以下代码:
self.navigationItem.backBarButtonItem?.action = #selector(ViewController.save(sender:))

...但是操作也没有执行。


我认为你只需要设置正确的返回箭头图像,这里是资源,下载并将其添加到自定义返回按钮即可。 - Santiago Carmona González
self.navigationItem.hidesBackButton = true; 如果为真的话,这意味着您将无法获取标准的返回按钮和其图标。 - Mannopson
@Mannopson 是的,我已将其设置为true。 - Nitesh
@Nitesh 我有同样的问题,也许这是一个bug。我使用了Swift 3.0和Xcode 8.0。 - Mannopson
@Nitesh,你已经尝试过使用UINavigationControllerDelegate方法来实现我的建议解决方案了吗? - regetskcob
6个回答

5
这可能有所帮助。这不会覆盖后退操作,但您可以执行其他任务。
Objective C
-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    if(self.isMovingFromParentViewController)
    {
        //On click of back or swipe back
    }
    if(self.isBeingDismissed)
    {
        //Dismissed
    }
    NSLog(@"%d",self.isBeingDismissed);
    NSLog(@"%d",self.isMovingFromParentViewController);
}

Swift

override func viewWillDisappear(_ animated: Bool)
{
    super.viewWillDisappear(animated);
    if self.isMovingFromParentViewController
    {
        //On click of back or swipe back
    }
    if self.isBeingDismissed
    {
        //Dismissed
    }
}

但是如果我这样做,警报不会被呈现。 - Nitesh
警告不会在此视图控制器上显示,因为它即将消失。尝试在即将显示的前一个视图控制器上显示。 - Amit Tandel

2

我找到了解决方案!

我在iOS 11和iOS 13上测试过,它可以正常工作 :)

protocol CustomNavigationViewControllerDelegate {
    func shouldPop() -> Bool
}

class CustomNavigationViewController: UINavigationController, UINavigationBarDelegate {
    var backDelegate: CustomNavigationViewControllerDelegate?

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

class SecondViewController: UIViewController, CustomNavigationViewControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()

        (self.navigationController as? CustomNavigationViewController)?.backDelegate = self
    }

    func shouldPop() -> Bool {
        if (needToShowAlert) {
            showExitAlert()
            return false

        } else {
            return true
        }
    }
}

1
谢谢,这对我很有效。不过,当SecondViewController消失时,您需要清除backDelegate吗? - Preston Landers

1
你需要在导航栏中添加自定义返回按钮,并为其添加操作。
      let backButton = UIBarButtonItem (image: UIImage(named: "ico-nav-prev")!, style: .plain, target: self, action: #selector(GoToBack))
      self.navigationItem.leftBarButtonItem = backButton
      self.navigationItem.hidesBackButton = true

     func GoToBack(){

        self.navigationController!.popViewController(animated: true)

      }

0

我不知道你想要实现什么,但是难道不是一个可能的解决方案吗?只要在vieWillDisappear:被调用时做你想要的事情。这也许是一个匹配的入口点,而不需要像其他答案中建议的那样去折腾后退按钮。

更好的方法 另一个选择是实现UINavigationControllerDelegate,将你的控制器设置为delegate,然后在navigationController(_:willShow:animated:)中实现你的警报。

参考此处


当用户按下返回按钮时,我需要显示一个警报。警报将有“是”和“否”按钮。我尝试在viewWillDisappear上执行此操作,但我的警报没有被呈现。 - Nitesh
添加了另一个选项,应该适合您的情况。 - regetskcob
它会在视图呈现时被调用,并且每次推送等操作都会被调用。我只想在返回时调用它。 - Nitesh
@Nitesh,你需要检查将要显示的viewController是否是你想要在警告框中显示的那个,然后就完成了! - regetskcob

0

我认为这个答案应该可以胜任。

你基本上可以使用默认样式创建按钮并注册选择器。

而且你可以尝试使用this来代替leftButton作为backButton

Objective-C

UIBarButtonItem *backBtn = [[UIBarButtonItem alloc] init];
[desVC.navigationItem setBackBarButtonItem:backBtn];

Swift

let backBtn = UIBarButtonItem()
self.navigationItem.backBarButtonItem = backBtn

0

将这行代码放在你的ParentViewControllerviewDidLoad方法中调用,而不是在ChildViewController中。

self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)

请从您的ChildViewController中删除以下代码行。
self.navigationItem.hidesBackButton = true

一切都会没问题!如果您需要为此转换创建一个操作,也就是当用户从您的ChildViewController点击后退按钮时。只需在您的ChildViewController内调用此方法即可。

 override func didMove(toParentViewController parent: UIViewController?) {
    super.didMove(toParentViewController: parent)

    if parent == nil {

    } else {

    }
}

编辑:

ChildViewController

 override func didMove(toParentViewController parent: UIViewController?) {
    super.didMove(toParentViewController: parent)

    if parent == nil {
        NotificationCenter.default.post(name: NSNotification.Name.init("Post"), object: nil)
    } else {

    }

}

父视图控制器

 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(self.handler(notification:)), name: NSNotification.Name.init(rawValue: "Post"), object: nil)

}

func handler(notification: Notification) {

    let alertController = UIAlertController(title: "Hello", message: nil, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
    self.present(alertController, animated: true, completion: nil)

}

这个可以工作但有一个问题:

警告:尝试在演示期间呈现 on !

因此我不建议使用。祝好运。


但是这样并没有呈现警告视图。 - Nitesh
但是这个警告会有一点问题。 - Mannopson
我的主要目的是在按下返回键时显示警报。 - Nitesh
我会向你展示。但是系统会发出警告。 - Mannopson
让我们在聊天中继续这个讨论 - Mannopson

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