iOS应用调用present方法弹出ViewController偶现失效问题
问题根因
- 当前调用
present方法的控制器已经存在未dismiss的presentedViewController,系统默认不允许同一个控制器同时present多个页面,此时调用会静默失败无报错 - 触发
present的代码偶发不在主线程执行,UI操作不在主线程执行时会出现各类无报错的异常表现 - 应用内存在层级高于主window的其他自定义window,导致主window弹出的控制器被遮盖,视觉上看起来没有弹出
- rootViewController 临时处于正在转场、布局的状态,此时调用present会被系统忽略
修复方案
- 不要直接硬取AppDelegate的rootViewController做present,优先获取当前应用最顶层的可见控制器来执行present操作,避免当前控制器存在presentedViewController的问题
- 所有UI相关操作统一包裹在主队列调度逻辑中,确保执行线程正确
- present前增加状态判断,如果当前控制器已经有presentedViewController,优先使用已弹出的控制器继续present新页面,或先dismiss旧页面再弹出新页面
优化后代码示例
// 全局工具方法:获取当前应用最顶层的可见控制器 extension UIViewController { static func topMostViewController() -> UIViewController? { guard let window = UIApplication.shared.delegate?.window as? UIWindow, let rootViewController = window.rootViewController else { return nil } var topController = rootViewController while let presentedController = topController.presentedViewController { topController = presentedController } return topController } } @IBAction func showHistoryButton(_ sender: MDCButton) { let exercisesHistoryVC = ExercisesHistoryViewController.instantiate(from: .Main) exercisesHistoryVC.modalPresentationStyle = .fullScreen // 强制主线程执行,用顶层控制器触发present避免冲突 DispatchQueue.main.async { guard let topVC = UIViewController.topMostViewController() else { return } topVC.present(exercisesHistoryVC, animated: true) } }
内容的提问来源于stack exchange,提问作者mistert69
相关产品推荐
相关产品推荐

