Swift中dismiss模态VC后调用popViewController无效问题
问题场景
需要在关闭模态展示的视图控制器后,执行popViewController返回导航栈的上一级页面,以下两种实现均无法正常生效:
第一种实现:
func showMessage(withTitle title: String, message: String) { let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) let alertAction = UIAlertAction(title: "ok", style: .default) { (_) in self.dismiss(animated: true) { self.navigationController?.popViewController(animated: true) } } alert.addAction(alertAction) present(alert, animated: true, completion: nil) }
第二种实现:
let controller = ViewController() controller?.popViewController(animated: true)
失效原因
- 第一种写法:调用dismiss的目标错误。代码触发时最顶层的模态视图是UIAlertController,
self.dismiss仅会关闭当前弹出的警告框,不会关闭你需要dismiss的模态VC。回调触发时当前控制器仍处于模态展示状态,并未处于导航控制器的栈结构中,self.navigationController为nil,pop操作无法执行。 - 第二种写法:操作的控制器实例错误。通过
ViewController()初始化的是全新的、未被加入任何导航栈的孤立实例,对该实例调用pop方法不会对当前已展示的界面产生任何效果。
正确实现
核心逻辑:弹出当前模态VC的控制器(即self.presentingViewController)才是处于导航栈内的页面,需要先dismiss当前模态VC,dismiss完成后再由这个弹出方的导航控制器执行pop操作。
替换alert按钮的回调代码即可:
let alertAction = UIAlertAction(title: "ok", style: .default) { [weak self] (_) in guard let self = self else { return } // 获取弹出当前模态VC的上级页面 guard let presentingVC = self.presentingViewController else { return } // 兼容presentingVC是普通页面/导航控制器两种场景 let targetNav = (presentingVC as? UINavigationController) ?? presentingVC.navigationController self.dismiss(animated: true) { targetNav?.popViewController(animated: true) } }
提示:闭包内使用
[weak self]是为了避免循环引用导致的内存泄漏。
内容的提问来源于stack exchange,提问作者JuFa512
相关产品推荐
相关产品推荐

