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

在SKScene中展示UIAlert的方法及无显示问题求助(附代码)

在SKScene中展示UIAlert的问题排查与解决

嘿,我来帮你搞定这个SKScene里弹不出UIAlert的问题!你当前的代码没反应,大概率是获取视图控制器的路径出了问题——链式调用self.view?.window?.rootViewController里的某一步可能返回了nil,或者拿到的控制器并不是当前能弹出弹窗的活跃控制器。

问题分析

你写的这段代码:

var alertController = UIAlertController(title: "Nothing Selected", message: "You have selected a picture.", preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(UIAlertAction(title: "HI!", style: UIAlertActionStyle.cancel, handler: nil))
self.view?.window?.rootViewController?.present(alertController, animated: true, completion: nil)

这里的self.view?.window?.rootViewController存在几个潜在问题:

  • 如果self.view还没被添加到窗口上,self.view?.window会是nil
  • 如果你的App结构是导航控制器(UINavigationController)或标签栏控制器(UITabBarController),直接用rootViewController拿到的是根控制器,而不是当前显示的子控制器,这时候调用present可能不会生效

解决方案

我给你几个靠谱的实现方式,按推荐程度排序:

1. 获取顶层视图控制器(最通用,推荐)

写一个UIViewController的扩展,用来找到当前App中最顶层的活跃视图控制器,不管你的界面结构是啥都能用:

extension UIViewController {
    static func topMostViewController() -> UIViewController? {
        // 找到当前的keyWindow
        guard let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
            return nil
        }
        var topVC = keyWindow.rootViewController
        // 一直找到最上层的presented控制器
        while let presentedVC = topVC?.presentedViewController {
            topVC = presentedVC
        }
        return topVC
    }
}

然后在你的SKScene里这么调用:

// 先拿到顶层控制器,再弹alert
if let topViewController = UIViewController.topMostViewController() {
    let alertController = UIAlertController(title: "Nothing Selected", message: "You have selected a picture.", preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "HI!", style: .cancel, handler: nil))
    topViewController.present(alertController, animated: true, completion: nil)
}

2. 直接获取SKView的父视图控制器

如果你的SKScene是直接添加在某个UIViewController的SKView上的,可以直接拿SKView的parentViewController:

if let parentVC = self.view?.parentViewController {
    let alertController = UIAlertController(title: "Nothing Selected", message: "You have selected a picture.", preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "HI!", style: .cancel, handler: nil))
    parentVC.present(alertController, animated: true, completion: nil)
}

这个方法更简洁,但只适用于SKScene的视图直接隶属于某个ViewController的情况。

3. 排查原代码的nil问题

如果想继续用你原来的思路,可以先打印排查哪一步是nil:

print("self.view: \(self.view)")
print("self.view?.window: \(self.view?.window)")
print("rootViewController: \(self.view?.window?.rootViewController)")

如果其中某一行输出是nil,就说明问题出在这一步——比如self.view为nil,说明你的SKScene还没被正确添加到视图层级里。

额外提示

记得在主线程里调用present方法!虽然UIKit的方法默认应该在主线程,但如果你的代码是在后台线程执行的,也会导致alert不显示。可以加个判断确保在主线程:

DispatchQueue.main.async {
    // 这里写弹alert的代码
}

内容的提问来源于stack exchange,提问作者B.Mahadewa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:47:41