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
相关产品推荐
相关产品推荐

