You need to enable JavaScript to run this app. Swift GAD插页广告未准备好崩溃及重复展示异常问题
优惠活动
大模型
产品
解决方案
定价
更多

Swift GAD插页广告未准备好崩溃及重复展示异常问题

GAD插页广告问题修复方案

问题1:广告未加载完成触发展示导致崩溃

根因:

  • CreateAd方法存在无限递归:当interstitial为空时,else分支直接递归调用CreateAd(),但方法内部没有任何广告加载逻辑,interstitial永远不会被赋值,递归会持续到栈空间耗尽,触发栈溢出类型的EXC_BAD_ACCESS错误
  • 额外问题:interstitial声明为隐式解包可选类型GADInterstitialAd!,空值时强制访问会直接崩溃;Timer的selector写的是ViewController.CreateAd,如果当前类名是JournalViewController会触发找不到方法的崩溃

问题2:广告关闭后循环展示不生效

根因:

  • 广告加载逻辑没有封装复用:你仅在viewDidLoad中执行了一次广告加载,没有封装独立的加载方法,单次展示后的广告失效后无法生成新的广告实例
  • CreateAd方法职责错误:该方法没有实现广告加载逻辑,仅做了存在时展示、不存在时递归的错误逻辑,在adDidDismissFullScreenContent中调用也无法生成新广告

修正后的完整实现代码

class JournalViewController: UIViewController, GADFullScreenContentDelegate {
    // 改为普通可选类型,避免隐式解包崩溃
    var interstitial: GADInterstitialAd?
    // 持有Timer避免提前释放,同时方便销毁
    var adTimer: Timer?
 
    override func viewDidLoad() {
        super.viewDidLoad()
        // 首次加载广告
        loadInterstitialAd()
        // 启动首次展示定时器
        resetAdTimer()
    }
    
    // 封装独立的广告加载方法,需要新加载时直接调用
    func loadInterstitialAd() {
        let request = GADRequest()
        GADInterstitialAd.load(
            withAdUnitID:"你的广告ID",
            request: request,
            completionHandler: { [weak self] ad, error in
                guard let self = self else { return }
                if let error = error {
                    print("Failed to load interstitial ad with error: \(error.localizedDescription)")
                    // 加载失败可以选择延迟重试,按需开启
                    // DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in
                    //     self?.loadInterstitialAd()
                    // }
                    return
                }
                self.interstitial = ad
                self.interstitial?.fullScreenContentDelegate = self
            }
        )
    }
    
    // 封装定时器重置方法
    func resetAdTimer() {
        // 先销毁旧定时器避免重复触发
        adTimer?.invalidate()
        let randomTime = Double(arc4random() + 20).truncatingRemainder(dividingBy: 60.0)
        adTimer = Timer.scheduledTimer(
            timeInterval: randomTime,
            target: self,
            selector: #selector(tryPresentInterstitialAd),
            userInfo: nil,
            repeats: false
        )
    }
    
    // 原CreateAd方法重命名,职责改为仅尝试展示广告
    @objc func tryPresentInterstitialAd() {
        if let interstitial = interstitial {
            // 广告存在直接展示
            interstitial.present(fromRootViewController: self)
        } else {
            print("Ad not ready, trigger reload")
            // 广告未加载完成,先触发加载,下次定时器再尝试展示
            loadInterstitialAd()
            // 直接重置定时器,下次再试
            resetAdTimer()
        }
    }
    
    // 广告关闭回调
    func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
        // 展示过的广告直接置空
        interstitial = nil
        // 加载新的广告
        loadInterstitialAd()
        // 重置下一次展示的定时器
        resetAdTimer()
    }
    
    // 页面销毁时销毁定时器,避免循环引用
    deinit {
        adTimer?.invalidate()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 18:45:03