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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:45:07