SwiftUI List视图Google横幅广告按需显示异常求助
解决SwiftUI List中广告加载失败时的空白问题
核心思路是给每个广告添加加载状态标记,根据状态控制广告视图的显示与隐藏,同时调整视图高度为0,避免List出现空白单元格。
修改后的完整代码
import SwiftUI struct ContentView: View { let bannerId = "ca-app-pub-3940256099942544/2934735716" // 存储每个广告的加载状态,初始都为未加载 @State private var adLoadedStates = Array(repeating: false, count: 10) var body: some View { ZStack { VStack(alignment: .center, spacing: 0) { navBar() .background(Color.blue) List(0..<10) { index in // 仅当广告加载成功时才显示广告单元格 if adLoadedStates[index] { HStack { Spacer() AdBannerView( bannerID: bannerId, adWidth: 320, adHeight: 50, isAdLoaded: $adLoadedStates[index] ) Spacer() } } Text("Hello world!") } .listStyle(.plain) Spacer() } } } // 自定义导航栏示例(可替换为你的实际实现) func navBar() -> some View { Text("导航栏") .foregroundColor(.white) .padding() } } import UIKit import GoogleMobileAds struct AdBannerView: UIViewControllerRepresentable { var bannerID: String var adWidth: CGFloat var adHeight: CGFloat // 绑定广告加载状态,用于通知父视图更新 @Binding var isAdLoaded: Bool func makeCoordinator() -> Coordinator { Coordinator(self) } func makeUIViewController(context: Context) -> UIViewController { print("makeUIViewController called") let bannerView = GADBannerView(frame: CGRect(x: 0, y: 0, width: adWidth, height: adHeight)) let viewController = UIViewController() bannerView.adUnitID = bannerID bannerView.rootViewController = viewController viewController.view.addSubview(bannerView) bannerView.load(GADRequest()) bannerView.delegate = context.coordinator // 初始状态设为未加载 isAdLoaded = false return viewController } @available(iOS 16.0, *) func sizeThatFits(_ proposal: ProposedViewSize, uiViewController: UIViewController, context: Context) -> CGSize? { // 根据加载状态返回高度,未加载则高度为0 isAdLoaded ? CGSize(width: adWidth, height: adHeight) : .zero } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { print("updateUIViewController called") // 同步隐藏/显示广告视图 if let bannerView = uiViewController.view.subviews.first as? GADBannerView { bannerView.isHidden = !isAdLoaded } } class Coordinator : NSObject, GADBannerViewDelegate { var parent : AdBannerView init(_ parent : AdBannerView) { self.parent = parent } public func bannerViewDidReceiveAd(_ bannerView: GADBannerView) { print("Ads received successfully") // 标记广告加载成功,触发父视图刷新 parent.isAdLoaded = true } public func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) { print("Ad loads to fail: \(error.localizedDescription)") // 标记广告加载失败,触发父视图刷新 parent.isAdLoaded = false } } }
关键修改点
- 添加加载状态数组:在
ContentView中用@State private var adLoadedStates存储每个广告的加载状态,确保每个广告单元格独立控制显示逻辑。 - 绑定状态到AdBannerView:给
AdBannerView添加@Binding var isAdLoaded,让子视图能将广告加载结果同步给父视图。 - 根据状态控制显示:
- 在
List中仅当对应广告的加载状态为true时,才渲染广告单元格。 - 在
AdBannerView的sizeThatFits方法中,未加载成功时返回高度为0,彻底消除空白占位。 - 在
updateUIViewController中同步隐藏广告视图,确保视觉上完全不显示未加载的广告。
- 在
- 代理方法更新状态:在Coordinator的广告加载成功/失败回调中,更新
isAdLoaded的状态值,触发SwiftUI视图自动刷新。
内容的提问来源于stack exchange,提问作者Karthik Kurdekar
相关产品推荐
相关产品推荐

