Swift问题:关闭模态ViewController时回退至导航栈根控制器而非调用者
咱们先梳理下你的跳转逻辑:RootVC 导航 push 到 VC A,VC A 弹出模态 VC,但点击模态 VC 的取消按钮后,没有回到 VC A 反而直接跳回了 RootVC —— 这种情况大概率是取消按钮的事件处理出了问题,或者模态跳转的配置有疏漏,我给你列几个最常见的排查方向:
1. 取消按钮误用了导航栈弹出方法(最常见)
这是最容易踩的坑:你可能在模态 VC 的取消按钮事件里,错误调用了导航栈的弹出方法,而不是关闭模态的 dismiss。
举个错误示例:
// 模态VC里的取消按钮点击事件(错误写法) @IBAction func cancelButtonTapped(_ sender: UIButton) { // 这个方法会让导航栈直接跳回根控制器,完全跳过关闭模态的逻辑 navigationController?.popToRootViewController(animated: true) }
正确的写法应该是调用 dismiss 来关闭模态,这样会回到发起 present 的 VC A:
// 模态VC里的取消按钮点击事件(正确写法) @IBAction func cancelButtonTapped(_ sender: UIButton) { dismiss(animated: true, completion: nil) }
2. 模态VC被嵌套在新导航控制器中,处理逻辑错误
如果你在 VC A 里把模态VC包裹进了新的导航控制器再弹出,比如:
// VC A里的模态调用代码 let modalVC = ModalViewController() let navVC = UINavigationController(rootViewController: modalVC) present(navVC, animated: true, completion: nil)
这时候如果在模态VC里调用 navigationController?.popViewController,只会在这个新导航栈里操作(而这个栈里只有模态VC自己),根本不会关闭模态。这种情况还是要调用 dismiss,或者给新导航栏的取消按钮绑定关闭模态的逻辑。
3. VC A被意外从导航栈移除
这种情况比较少见,但也有可能:在弹出模态VC之后,某个地方误调用了 popViewController 把 VC A 从导航栈里移除了。这时候关闭模态后,导航栈里只剩 RootVC,自然就直接回到根控制器了。
你可以在 VC A 里加个打印排查:
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) print("VC A 是否被弹出导航栈:\(isMovingFromParent)") }
如果打印结果为 true,那就要找哪里误触发了弹出VC A的逻辑。
4. 自定义转场动画干扰导航栈状态
如果你给模态跳转加了自定义转场动画,极少数情况下可能会干扰导航栈的状态,但如果没做自定义转场,可以先排除这个可能性。
优先检查取消按钮的实现,90%的概率是这里的方法调用错了~
内容的提问来源于stack exchange,提问作者user3628240

