Swift中AdMob激励广告userDidEarn回调后无法弹出Alert问题求助
解决AdMob激励广告观看后提示框不弹出的问题
看起来你遇到的核心问题是激励广告观看完成后,showAlert方法没有正确弹出提示框,结合你的代码,我整理了几个最可能的原因和对应的修复方案:
1. UI操作必须在主线程执行
AdMob的rewardedAd(_:userDidEarn:)回调大概率是在后台线程触发的,而iOS要求所有UI相关操作(比如present提示框)必须在主线程执行。你的showAlert直接在回调闭包里调用,很可能因为线程问题导致无法弹出。
修复代码:
把showAlert的调用包裹在主线程异步任务里:
func rewardedAd(_ rewardedAd: GADRewardedAd, userDidEarn reward: GADAdReward) { rewardedAdService.reloadRewardedAd() rewardedAdService.rewardedAdIsWatched { (newMoney) in // 确保UI更新在主线程 DispatchQueue.main.async { trainingStartView.coinShowView.number = newMoney self.showAlert(title: "You got rich 螺", message: "You've earned 30 Coins!!!") } } }
2. 确认self是当前活跃的ViewController
如果调用present的self已经被释放,或者不在当前视图层级的栈顶,提示框也无法弹出。可以通过两种方式优化:
- 用
[weak self]避免循环引用,同时判断self不为nil - 获取当前应用的顶层ViewController来present提示框,更可靠
优化后的代码:
首先给UIViewController扩展一个获取顶层VC的方法:
extension UIViewController { func topMostViewController() -> UIViewController { if let presented = self.presentedViewController { return presented.topMostViewController() } if let navigation = self as? UINavigationController { return navigation.visibleViewController?.topMostViewController() ?? navigation } if let tab = self as? UITabBarController { return tab.selectedViewController?.topMostViewController() ?? tab } return self } }
然后修改showAlert方法:
func showAlert(title:String = "Oops!",message:String = "Something went wrong"){ let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) // 获取顶层ViewController来present提示框 guard let topVC = UIApplication.shared.windows.first?.rootViewController?.topMostViewController() else { print("无法找到可用的ViewController来展示提示框") return } topVC.present(alert, animated: true, completion: nil) }
同时在回调里使用弱引用:
rewardedAdService.rewardedAdIsWatched { [weak self] (newMoney) in guard let self = self else { return } DispatchQueue.main.async { self.trainingStartView.coinShowView.number = newMoney self.showAlert(title: "You got rich 螺", message: "You've earned 30 Coins!!!") } }
3. 验证rewardedAdIsWatched闭包是否被执行
有时候可能是rewardedAdService.rewardedAdIsWatched的逻辑问题,导致闭包根本没触发。可以在闭包里加日志确认:
rewardedAdService.rewardedAdIsWatched { (newMoney) in print("奖励逻辑已触发,新金币数:\(newMoney)") // 加这句日志验证 DispatchQueue.main.async { // ... 其他代码 } }
如果控制台没有输出这句话,那问题出在rewardedAdService的逻辑里,需要检查这个方法是否正确触发了闭包。
内容的提问来源于stack exchange,提问作者batuhankrbb
相关产品推荐
相关产品推荐

