Swift游戏开发:GameScene无法调用ViewController的updateScore函数问题
问题排查与解决方案
核心问题:viewController 为 nil,导致可选链调用失败
GameScene 里的 viewController?.updateScore(...) 使用了可选链,当 viewController 是 nil 时,后续代码不会执行——这就是你看不到打印输出的直接原因。以下是具体问题点和修复步骤:
1. 正确声明 GameScene 的 viewController 属性
GameScene 必须先定义 viewController 可选属性,且要用 weak 修饰避免循环引用(ViewController 持有 GameScene,若 GameScene 强引用 ViewController 会导致内存泄漏):
class GameScene: SKScene { weak var viewController: ViewController? // 关键:声明弱引用可选属性 var score = 0 // 游戏内的分数变量 // 分数增长逻辑示例 func increaseScore() { score += 1 updateViewScore() } func updateViewScore() { // 传递实际的score值,而非固定的10 viewController?.updateScore(score: score) } }
2. 修正 ViewController 中 GameScene 的初始化逻辑
不能在类的顶层直接初始化 gameScene(此时 view.bounds 还未完成初始化),必须放在视图生命周期方法(如 viewDidLoad)中,同时要将 GameScene 展示到 SKView 上:
class ViewController: UIViewController { var gameScene: GameScene! var score = 0 // ViewController侧的分数变量 var interstitial: GADInterstitial? // 你的插屏广告变量 override func viewDidLoad() { super.viewDidLoad() // 初始化GameScene gameScene = GameScene(size: view.bounds.size) gameScene.viewController = self // 将GameScene展示到SKView(这步极易遗漏) guard let skView = view as? SKView else { print("当前视图不是SKView") return } skView.presentScene(gameScene) } func updateScore(score: Int) { print("updateScore was called with score: \(score)") self.score = score // 更新ViewController侧的分数 popUp(with: score) } // 移除@IBAction,改为普通方法(代码调用而非按钮触发) func popUp(with score: Int) { if score % 10 == 0 { // 增加广告就绪判断,避免未就绪时调用 if interstitial != nil && interstitial!.isReady { interstitial?.present(fromRootViewController: self) // 广告展示后重新加载,保证下一次触发时有可用广告 interstitial = createNewInterstitial() } else { print("Ad wasn't ready") } } } // 辅助方法:创建新的插屏广告(示例) func createNewInterstitial() -> GADInterstitial { let interstitial = GADInterstitial(adUnitID: "你的广告ID") interstitial.load(GADRequest()) return interstitial } }
3. 广告触发逻辑优化
- 原
popUp是@IBAction,适合按钮触发场景,代码调用时改为普通方法更合理 - 增加
isReady判断,确保广告就绪后再展示 - 广告展示后重新加载,保证后续触发时有可用广告
内容的提问来源于stack exchange,提问作者Sider the Programmer
相关产品推荐
相关产品推荐

