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

SwiftUI集成AdMob:广告加载失败时隐藏视图的实现问题

问题:广告加载失败时无法更新绑定变量隐藏视图

用户尝试在广告加载失败时通过isLoaded绑定变量隐藏广告视图,但当前代码中的Coordinator类无法访问@Binding var isLoaded,导致无法执行isLoaded = false的操作。

原代码:

struct BottomBannerView : View {
    
    @State var isLoaded: Bool = true
    
    var body : some View{
        AdViewBottom(isLoaded: self.$isLoaded)
            .frame(width: 320, height: isLoaded ? 50 : 0)
    }
}

struct AdViewBottom: UIViewRepresentable {
    
    @Binding var isLoaded: Bool
    
    class Coordinator: NSObject, GADBannerViewDelegate {
        func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
            print("Ad failed to load: \(error.localizedDescription)")
            isLoaded = false // 无法访问该变量
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator()
    }

    func makeUIView(context: Context) -> GADBannerView {
        let banner = GADBannerView(adSize: GADAdSizeBanner)
        banner.adUnitID = "ca-app-pub-xxx~xxxx"
        // banner.rootViewController = UIApplication.shared.windows.first?.rootViewController // The root view controller is needed to present full screen content.
        banner.delegate = context.coordinator
        banner.load(GADRequest())
        banner.backgroundColor = .black
        return banner
    }

    func updateUIView(_ uiView: GADBannerView, context: Context) {
        // 无需更新
    }
}

解决方案

核心思路是让Coordinator持有Binding<Bool>的引用,从而在代理方法中更新绑定变量。具体修改步骤如下:

  1. 给Coordinator添加@Binding var isLoaded: Bool属性
  2. 在makeCoordinator()方法中创建Coordinator时,传入当前的isLoaded绑定
  3. 在代理方法中直接更新该绑定变量

修改后的完整代码:

struct BottomBannerView : View {
    
    @State var isLoaded: Bool = true
    
    var body : some View{
        AdViewBottom(isLoaded: self.$isLoaded)
            .frame(width: 320, height: isLoaded ? 50 : 0)
    }
}

struct AdViewBottom: UIViewRepresentable {
    
    @Binding var isLoaded: Bool
    
    // 修改Coordinator,添加Binding属性
    class Coordinator: NSObject, GADBannerViewDelegate {
        @Binding var isLoaded: Bool
        
        // 初始化时传入Binding
        init(isLoaded: Binding<Bool>) {
            _isLoaded = isLoaded
        }
        
        func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
            print("Ad failed to load: \(error.localizedDescription)")
            isLoaded = false // 现在可正常更新绑定变量
        }
        
        // 可选:添加广告加载成功的代理方法,恢复视图显示
        func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
            isLoaded = true
        }
    }

    func makeCoordinator() -> Coordinator {
        // 创建Coordinator时传入isLoaded绑定
        Coordinator(isLoaded: $isLoaded)
    }

    func makeUIView(context: Context) -> GADBannerView {
        let banner = GADBannerView(adSize: GADAdSizeBanner)
        banner.adUnitID = "ca-app-pub-xxx~xxxx"
        // 适配iOS13+的rootViewController获取方式
        if let rootVC = UIApplication.shared.connectedScenes
            .filter({$0.activationState == .foregroundActive})
            .compactMap({$0 as? UIWindowScene})
            .first?.windows
            .filter({$0.isKeyWindow}).first?.rootViewController {
            banner.rootViewController = rootVC
        }
        banner.delegate = context.coordinator
        banner.load(GADRequest())
        banner.backgroundColor = .black
        return banner
    }

    func updateUIView(_ uiView: GADBannerView, context: Context) {
        // 无需额外操作
    }
}

关键说明

  • 通过给Coordinator添加@Binding属性并在初始化时传入,让协调器获得修改绑定变量的权限
  • 额外添加bannerViewDidReceiveAd代理方法,确保广告加载成功时重新显示视图,逻辑更完整
  • 修复了rootViewController的获取方式,适配iOS13及以上系统(原代码方式在iOS13+环境下可能失效)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 20:22:40