如何实现所有ViewController共用共享AdMob广告?遇初始化报错求助
嘿,我一眼就看出问题出在哪了——你在AppDelegate里提前调用了adBannerView.load(GADRequest()),但这时候rootViewController还没设置!AdMob明确要求必须先给GADBannerView指定rootViewController,才能发起广告请求,这就是你看到那个报错的根本原因。
而且你现在的逻辑是在每个ViewController里才设置rootViewController,但广告请求早就提前发出去了,完全顺序颠倒了。下面给你一套完整的修正方案,既能实现所有VC共用同一个Banner,又能符合AdMob的要求:
第一步:修改AppDelegate的Banner初始化逻辑
我们把广告加载的时机延后,只在第一个VC准备好显示Banner时再触发加载,同时新增一个方法来统一处理广告加载:
class AppDelegate: UIResponder, UIApplicationDelegate, GADBannerViewDelegate { var window: UIWindow? var adBannerView = GADBannerView() // 全局共用的Banner实例 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // 初始化Google移动广告SDK GADMobileAds.configure(withApplicationID: "ca-app-pub-xxxxxx") // 只配置Banner的基础属性,先不加载广告 adBannerView.adUnitID = "ca-app-pub-xxxx" adBannerView.delegate = self adBannerView.clipsToBounds = true adBannerView.isHidden = true // 初始状态隐藏 return true } // 广告加载成功,显示Banner func adViewDidReceiveAd(_ bannerView: GADBannerView) { adBannerView.isHidden = false } // 广告加载失败,隐藏Banner并打印错误信息 func adView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: GADRequestError) { adBannerView.isHidden = true print("广告加载失败: \(error.localizedDescription)") } // 新增方法:确保rootViewController设置后再加载广告 func loadBannerAd(withRootVC rootVC: UIViewController) { adBannerView.rootViewController = rootVC // 只有当广告未就绪时才发起请求,避免重复加载 if !adBannerView.isReady { adBannerView.load(GADRequest()) } } }
第二步:修改ViewController的Banner添加逻辑
每次切换VC时,我们需要把Banner从之前的父视图移除,重新添加到当前VC,并更新rootViewController,保证广告交互始终关联当前页面:
func addBannerToView() { // 获取AppDelegate实例 guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return } // 先把Banner从之前的视图中移除,防止重复添加 appDelegate.adBannerView.removeFromSuperview() // 设置当前ViewController为Banner的rootViewController appDelegate.adBannerView.rootViewController = self // 配置Banner的尺寸和位置(底部固定) appDelegate.adBannerView.adSize = kGADAdSizeBanner let bannerHeight = appDelegate.adBannerView.frame.height appDelegate.adBannerView.frame = CGRect( x: 0, y: view.frame.height - bannerHeight, width: view.frame.width, height: bannerHeight ) // 将Banner添加到当前视图 view.addSubview(appDelegate.adBannerView) // 触发广告加载(如果还没加载的话) appDelegate.loadBannerAd(withRootVC: self) }
关键注意点
- 每次进入新的ViewController时,都要调用
addBannerToView()方法,这样Banner会跟随当前页面,并且rootViewController始终是正确的,避免广告跳转后返回错误页面的问题。 - 为什么不在AppDelegate提前加载?因为AdMob的
rootViewController必须绑定当前显示的VC,否则广告的交互(比如打开网页、跳转App Store)会出现异常。 adBannerView.isReady判断可以避免重复发起广告请求,节省资源。
这样修改后,你就不会再收到那个rootViewController未设置的错误,同时所有ViewController都能共用同一个Banner实例啦!
内容的提问来源于stack exchange,提问作者Vetuka
相关产品推荐
相关产品推荐

