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

SwiftUI项目集成AdMob遇报错:如何解决委托与视图控制器问题?

SwiftUI集成AdMob的两个常见问题及修复方案

问题描述

作为SwiftUI新手,开发首款游戏时参照旧视频集成AdMob,遇到两个问题:

1. 编译错误:方法未找到

错误代码片段:

func present() {
    guard let root = UIApplication.shared.firstKeyWindowRootViewController() else {return}
    guard let interstitial else {
        print("Not Ready! Loading now!") ; load() ; return
    }
}

错误信息:

Value of type 'UIApplication' has no member 'firstKeyWindowRootViewController'

2. Swift 6兼容性警告:Main Actor隔离问题

警告代码片段:

func load() {
    let request = Request()
    InterstitialAd.load(with: adUnitID, request: request){ [weak self] ad, error in
        if let error { print("Failed to load \(error)"); return}
        self?.interstitial = ad
        self?.interstitial?.fullScreenContentDelegate = self
        print("interstitial has loaded!!!")
    }
}

警告信息:

Main actor-isolated conformance of 'InterstitialAdManager' to 'FullScreenContentDelegate' cannot be used in nonisolated context; this is an error in the Swift 6 language mode


修复方案

解决编译错误:修正方法名拼写

问题出在UIApplication扩展的方法名拼写错误:扩展里定义的是firstKeyWindowRootViewContoller()(末尾少了一个r),但调用时写的是firstKeyWindowRootViewController()。

修正扩展方法名(推荐,符合标准拼写):

private extension UIApplication {
    // 修正拼写为 firstKeyWindowRootViewController
    func firstKeyWindowRootViewController() -> UIViewController? {
        connectedScenes
            .compactMap { ($0 as? UIWindowScene)?.keyWindow}
            .first?
            .rootViewController
    }
}

同时,present()方法缺少展示广告的核心代码,补充完整:

func present() {
    guard let root = UIApplication.shared.firstKeyWindowRootViewController() else {return}
    guard let interstitial else {
        print("Not Ready! Loading now!") ; load() ; return
    }
    // 新增:展示 interstitial 广告
    interstitial.present(fromRootViewController: root)
}

解决Main Actor警告

FullScreenContentDelegate属于Main Actor隔离的协议,而InterstitialAd.load的回调运行在非Main Actor上下文,直接赋值代理会触发警告。有两种修复方式:

方式1:在回调中切换到Main Actor执行赋值

func load() {
    let request = Request()
    
    InterstitialAd.load(with: adUnitID, request: request){ [weak self] ad, error in
        if let error { 
            print("Failed to load \(error)")
            return
        }
        guard let self = self else { return }
        // 切换到Main Actor队列执行代理赋值
        Task { @MainActor in
            self.interstitial = ad
            self.interstitial?.fullScreenContentDelegate = self
            print("interstitial has loaded!!!")
        }
    }
}

方式2:给整个管理器类标记Main Actor

直接让InterstitialAdManager类所有代码都运行在Main Actor上,从根源避免上下文不匹配:

@MainActor
final class InterstitialAdManager:NSObject, ObservableObject, FullScreenContentDelegate {
    private let adUnitID = "ca-app-pub-3940256099942544/1033173712"
    private var interstitial: InterstitialAd?
    
    // ... 原有方法代码保持不变 ...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 16:44:53