SwiftUI展示AdMob插页广告导致导航流程中断问题求助
解决AdMob插页广告后详情视图自动返回Dashboard的问题
我的应用包含Dashboard视图,用户点击其中项目时应导航至详情视图并全屏展示。但当前存在问题:展示AdMob插页广告后,详情视图(子视图)仅短暂显示,随即自动返回Dashboard视图(父视图)。Dashboard跳转至详情视图的代码为标准实现,以下是我的AdMob管理代码:
class InterstitialAdsManager: NSObject, GADFullScreenContentDelegate, ObservableObject { @Published var interstitialAdLoaded: Bool = false var interstitialAd: GADInterstitialAd? let AD_UNIT_ID = "ca-app-pub-3940256032142544/xxxxxxxxx" override init() { super.init() } func loadInterstitialAd() { GADInterstitialAd.load(withAdUnitID: AD_UNIT_ID, request: GADRequest()) { [weak self] ad, error in guard let self = self else { return } if let error = error { print("🔴: \(error.localizedDescription)") self.interstitialAdLoaded = false return } print("🟢: Loading succeeded") self.interstitialAdLoaded = true self.interstitialAd = ad self.interstitialAd?.fullScreenContentDelegate = self } } func displayInterstitialAd(viewController: UIViewController) { let root = UIApplication.shared.windows.last?.rootViewController if let ad = interstitialAd { ad.present(fromRootViewController: root) self.interstitialAdLoaded = false } else { print("🔵: Ad wasn't ready") self.interstitialAdLoaded = false self.loadInterstitialAd() } } func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) { print("🟡: Failed to display interstitial ad") self.loadInterstitialAd() } func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) { print("🤩: Displayed an interstitial ad") self.interstitialAdLoaded = false } func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) { print("😔: Interstitial ad closed") } }
问题根源
你在displayInterstitialAd方法里使用全局的UIApplication.shared.windows.last?.rootViewController作为广告的展示根控制器,这会让广告直接覆盖整个应用的根视图栈。当广告关闭后,系统会自动回到根控制器层级,导致刚推入导航栈的详情视图被强制退回。
修复方案
1. 修正广告展示的控制器
把广告展示的根控制器改成传入的viewController参数,这样广告会在当前导航栈的上下文内展示,不会破坏原有视图层级:
func displayInterstitialAd(viewController: UIViewController) { if let ad = interstitialAd { // 替换全局root为传入的当前控制器 ad.present(fromRootViewController: viewController) self.interstitialAdLoaded = false } else { print("🔵: Ad wasn't ready") self.interstitialAdLoaded = false self.loadInterstitialAd() } }
2. 调整广告与导航的时序
避免同时触发导航和广告展示,二选一拆分流程:
- 先展示广告,再进详情:在
adDidDismissFullScreenContent回调中执行导航到详情视图的逻辑 - 先进详情,再展示广告:在详情视图的
viewDidAppear方法里调用广告展示方法,确保视图已经完成入栈
3. 补充广告关闭后的加载逻辑
在广告关闭后重新加载下一个广告,保证后续展示可用:
func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) { print("😔: Interstitial ad closed") // 重新加载广告,为下一次展示做准备 self.loadInterstitialAd() }
额外注意事项
- 不要在导航跳转的同步流程里触发广告展示,必须拆分为异步操作(等待广告关闭再导航,或导航完成后再弹广告)
- 确保
interstitialAdLoaded的状态更新准确,避免重复触发广告展示
内容的提问来源于stack exchange,提问作者Learn2Code
相关产品推荐
相关产品推荐

