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>的引用,从而在代理方法中更新绑定变量。具体修改步骤如下:
- 给
Coordinator添加@Binding var isLoaded: Bool属性 - 在
makeCoordinator()方法中创建Coordinator时,传入当前的isLoaded绑定 - 在代理方法中直接更新该绑定变量
修改后的完整代码:
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
相关产品推荐
相关产品推荐

