You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS中点击UINavigationController返回按钮能否中断viewWillDisappear执行?

核心问题说明

你没法在viewWillDisappear里中断返回流程,因为这个方法被调用时,视图控制器已经进入出栈流程,无法终止,必须在pop动作触发前做校验拦截。

实现方案

方案1:自定义导航栏返回按钮(全iOS版本兼容,通用性最强)

直接替换系统默认返回按钮,点击时先做业务校验,校验通过再执行返回逻辑,同时可兼容侧滑返回手势的校验:

  1. 首先在viewDidLoad中配置自定义返回按钮和侧滑手势代理
override func viewDidLoad() {
    super.viewDidLoad()
    // 替换系统默认返回按钮
    let backButton = UIBarButtonItem(image: UIImage(systemName: "chevron.backward"), style: .plain, target: self, action: #selector(backButtonTapped))
    navigationItem.leftBarButtonItem = backButton
    // 配置侧滑返回手势代理,实现侧滑时也触发校验
    navigationController?.interactivePopGestureRecognizer?.delegate = self
}
  1. 实现返回按钮点击校验逻辑
@objc private func backButtonTapped() {
    // 替换为你自己的业务校验条件,比如此处判断名称不能为空
    guard let name = nameField.text, !name.isEmpty else {
        // 条件不满足,弹出提示,不执行返回
        let alert = UIAlertController(title: "提示", message: "名称为必填项,请填写后再返回", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "知道了", style: .default))
        present(alert, animated: true)
        return
    }
    // 条件满足,执行返回
    navigationController?.popViewController(animated: true)
}
  1. 实现侧滑手势的校验逻辑
extension DetailViewController: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        guard gestureRecognizer == navigationController?.interactivePopGestureRecognizer else {
            return true
        }
        // 和返回按钮共用同样的校验逻辑
        guard let name = nameField.text, !name.isEmpty else {
            let alert = UIAlertController(title: "提示", message: "名称为必填项,请填写后再返回", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "知道了", style: .default))
            present(alert, animated: true)
            return false
        }
        return true
    }
}

方案2:使用导航控制器代理拦截(iOS16+ 更简洁)

iOS16新增了导航控制器的pop拦截代理方法,不需要自定义返回按钮即可实现拦截:

// 在viewDidLoad中设置代理
override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.delegate = self
}

// 实现代理方法
extension DetailViewController: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, shouldPop viewController: UIViewController) -> Bool {
        // 只拦截当前详情页的pop动作
        guard viewController === self else { return true }
        // 替换为你的业务校验条件
        guard let name = nameField.text, !name.isEmpty else {
            let alert = UIAlertController(title: "提示", message: "名称为必填项,请填写后再返回", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "知道了", style: .default))
            present(alert, animated: true)
            return false
        }
        return true
    }
}

注意:使用该方案时如果多个页面都用到了导航控制器代理,需要注意代理的切换,避免互相冲突。

你原有代码viewWillDisappear中的保存逻辑不需要修改,只有校验通过执行返回时才会触发该方法,保存逻辑会正常执行。

内容的提问来源于stack exchange,提问作者Iggy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 03:27:04