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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 17:52:40