为模态推送转场添加条件,满足特定条件才允许返回上一控制器
解决方案:拦截导航返回与侧滑手势,阻止不符合条件的返回
这个需求完全可以实现!核心思路是拦截导航控制器的返回行为(包括系统返回按钮点击和侧滑返回手势),在触发返回前检查条件,不满足时弹出提示框。下面分两种常用场景给出具体实现:
一、自定义返回按钮(推荐,更灵活可控)
如果你的导航栏返回按钮是自定义的,直接给按钮添加点击事件,在事件里判断条件:
class SecondViewController: UIViewController { // 假设condition是你要判断的条件,比如表单是否填写完成 var condition = false override func viewDidLoad() { super.viewDidLoad() // 自定义返回按钮 let backButton = UIBarButtonItem(title: "返回", style: .plain, target: self, action: #selector(backButtonTapped)) navigationItem.leftBarButtonItem = backButton } @objc private func backButtonTapped() { guard condition else { // 条件不满足,弹出提示 let alert = UIAlertController(title: "提示", message: "You can't go back until [condition]", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return } // 条件满足,执行返回 navigationController?.popViewController(animated: true) } }
二、拦截系统返回按钮与侧滑手势
如果想保留系统默认的返回按钮样式,需要借助UINavigationControllerDelegate来拦截返回行为,同时处理侧滑手势:
1. 给当前导航控制器设置代理
在第二个视图控制器的viewWillAppear里设置代理,viewWillDisappear里移除(避免影响其他页面):
class SecondViewController: UIViewController, UINavigationControllerDelegate { var condition = false // 保存系统默认的侧滑手势代理 private var originalInteractivePopGestureDelegate: UIGestureRecognizerDelegate? override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.delegate = self // 保存并禁用侧滑手势的默认代理,方便我们自己控制 originalInteractivePopGestureDelegate = navigationController?.interactivePopGestureRecognizer?.delegate navigationController?.interactivePopGestureRecognizer?.delegate = self } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) navigationController?.delegate = nil // 恢复侧滑手势的默认代理 navigationController?.interactivePopGestureRecognizer?.delegate = originalInteractivePopGestureDelegate } }
2. 实现导航控制器代理方法,拦截返回
extension SecondViewController { func navigationController(_ navigationController: UINavigationController, shouldPop viewController: UIViewController) -> Bool { guard condition else { // 弹出提示 let alert = UIAlertController(title: "提示", message: "You can't go back until [condition]", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) // 这里返回false,阻止系统执行pop操作 return false } return true } // 处理侧滑手势,条件不满足时禁用侧滑 func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { guard gestureRecognizer == navigationController?.interactivePopGestureRecognizer else { return true } return condition } }
注意事项
- 如果你用的是Objective-C,代码逻辑是一致的,只是语法上调整即可。
- 确保
condition的状态是实时更新的,比如用户完成操作后要把它设为true。 - 第二种方式里,别忘了在页面消失时恢复导航控制器的代理和侧滑手势的代理,不然会影响其他页面的正常返回。
内容的提问来源于stack exchange,提问作者e2r3p13
相关产品推荐
相关产品推荐

