SwiftUI中展示GADInterstitialAd时如何避免MainView重载
解决SwiftUI展示插页广告时MainView重载的问题
问题根源在于你使用fullScreenCover的方式——SwiftUI的全屏模态展示会强制触发底层MainView的onDisappear回调,关闭广告后又会触发onAppear,这是模态视图的默认生命周期行为。要避免视图重载,你可以直接在UIKit层级从MainView对应的UIViewController展示广告,完全绕过SwiftUI的模态修饰符。
具体实现方案
1. 桥接SwiftUI与UIKit,获取当前视图控制器引用
创建一个隐藏的桥接视图,用来在SwiftUI中拿到对应的UIKit视图控制器实例:
struct ViewControllerHolder: UIViewControllerRepresentable { @Binding var viewController: UIViewController? func makeUIViewController(context: Context) -> UIViewController { UIViewController() } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { DispatchQueue.main.async { // 获取当前SwiftUI视图对应的父级UIViewController self.viewController = uiViewController.parent } } }
2. 封装广告管理逻辑
把广告加载、展示的逻辑单独封装成一个可观察对象,方便在SwiftUI中调用:
import GoogleMobileAds class InterstitialAdManager: ObservableObject { private(set) var interstitialAd: GADInterstitialAd? // 加载插页广告 func loadAd(withUnitID unitID: String) { GADInterstitialAd.load(withAdUnitID: unitID, request: GADRequest()) { ad, error in if let error = error { print("广告加载失败: \(error.localizedDescription)") return } self.interstitialAd = ad print("广告加载完成") } } // 直接从指定视图控制器展示广告 func showAd(from viewController: UIViewController?, completion: @escaping () -> Void) { guard let vc = viewController, let ad = interstitialAd else { print("广告未准备就绪或无可用视图控制器") completion() return } ad.present(fromRootViewController: vc) completion() print("广告已展示") // 广告展示后清空引用,下次需重新加载 self.interstitialAd = nil } }
3. 在MainView中集成使用
不再依赖fullScreenCover,直接通过广告管理器展示广告:
struct MainView: View { @StateObject private var adManager = InterstitialAdManager() @State private var currentViewController: UIViewController? var body: some View { // 你的主视图内容 VStack(spacing: 20) { Text("主视图核心内容") .font(.title) Button("展示插页广告") { adManager.showAd(from: currentViewController) { // 广告展示完成后的后续逻辑 } } .buttonStyle(.borderedProminent) } .onAppear { // 页面加载时预加载广告 adManager.loadAd(withUnitID: "你的广告单元ID") } // 嵌入桥接视图,悄悄获取当前UIViewController引用 .background(ViewControllerHolder(viewController: $currentViewController)) } }
方案优势说明
直接调用UIKit的present方法展示广告,完全绕过了SwiftUI的模态视图机制,MainView不会感知到广告的展示/关闭,自然不会触发onDisappear和onAppear回调,也就避免了视图重载问题。
内容的提问来源于stack exchange,提问作者Jabed Dhali
相关产品推荐
相关产品推荐

