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

Swift开发中present弹出的模态弹窗上UIAlertController无法显示问题求助

问题原因
  • 当你使用.overCurrentContext样式present出guardViewController后,AppDelegate对应的根视图控制器已经存在处于显示状态的presented控制器(即guardViewController),iOS不允许在已经有presented控制器的视图控制器上直接present新的控制器,因此你的alert请求会被系统静默忽略,部分场景下控制台会输出对应的冲突警告。
  • 你所有的present操作都默认通过AppDelegate的根控制器执行,没有考虑当前的控制器present栈状态,导致present目标错误。
解决方案

方案1:直接在当前guardViewController中present alert(改动最小,优先推荐)

弹窗本身就应该由当前处于前台显示的父控制器弹出,把closeTapped里的present和dismiss逻辑都改为当前控制器调用即可,修改后代码如下:

@IBAction func closeTapped(_ sender: Any) {
    let alert = UIAlertController(title: "Alert", message: "Are You Sure", preferredStyle: .alert)
    let proceedAction = UIAlertAction(title: "Proceed", style: .destructive) { (action) in
        // 直接调用当前控制器的dismiss,不需要走AppDelegate
        self.dismiss(animated: true)
    }
    alert.addAction(proceedAction)
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
    alert.addAction(cancelAction)

    if let popoverController = alert.popoverPresentationController {
        popoverController.sourceView = sender as? UIView
        popoverController.sourceRect = CGRect(x: (sender as AnyObject).bounds.midX, y: (sender as AnyObject).bounds.midY, width: 0, height: 0)
        popoverController.permittedArrowDirections = [.any]
    }
    // 直接由当前显示的guardViewController present alert
    self.present(alert, animated: true)
}

方案2:封装顶层控制器获取逻辑,统一全局弹窗

如果你需要全局通用的弹窗能力,可以封装获取当前最顶层控制器的扩展,无论当前present栈是什么状态,都用最顶层的控制器弹出内容:
首先添加UIViewController扩展:

extension UIViewController {
    static func getTopMostVC() -> UIViewController? {
        let keyWindow = UIApplication.shared.connectedScenes
            .filter({$0.activationState == .foregroundActive})
            .compactMap({$0 as? UIWindowScene})
            .first?.windows
            .first(where: \.isKeyWindow)
        var topVC = keyWindow?.rootViewController
        while let presentedVC = topVC?.presentedViewController {
            topVC = presentedVC
        }
        return topVC
    }
}

需要弹窗时调用即可:

UIViewController.getTopMostVC()?.present(alert, animated: true)

内容的提问来源于stack exchange,提问作者Ng1002

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 10:24:04