iOS集成AdMob遇Thread 1错误:隐式解包Optional值为nil
解决AdMob初始化时的"Unexpectedly found nil"崩溃问题
你遇到的这个崩溃完全是因为代码执行顺序错误导致的:你在还没初始化bannerView的情况下,就尝试给它的adUnitID等属性赋值,而bannerView被声明为隐式解包的Optional(var bannerView: GADBannerView!),此时访问它自然会触发nil崩溃。
问题代码的关键错误点
- 你先执行了
bannerView.adUnitID = "ca-app-pub-xxxxx/xxxxx",但此时bannerView还没有被实例化,值为nil - 初始化
bannerView的代码bannerView = GADBannerView(adSize: kGADAdSizeBanner)被放在了属性赋值之后 - 辅助函数
addBannerViewToView被定义在了viewDidLoad内部,虽然能运行,但不符合Swift代码规范
修正后的完整代码
import UIKit import GoogleMobileAds class ViewController: UIViewController, GADBannerViewDelegate { var bannerView: GADBannerView! override func viewDidLoad() { super.viewDidLoad() // 第一步:先初始化bannerView实例 bannerView = GADBannerView(adSize: kGADAdSizeBanner) bannerView.delegate = self // 第二步:再设置广告单元ID和根视图控制器 bannerView.adUnitID = "ca-app-pub-xxxxx/xxxxx" bannerView.rootViewController = self // 第三步:添加到视图并设置约束 addBannerViewToView(bannerView) // 最后:发起广告请求 bannerView.load(GADRequest()) } // 把辅助函数移到viewDidLoad外部,符合代码规范 func addBannerViewToView(_ bannerView: GADBannerView) { bannerView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(bannerView) view.addConstraints( [NSLayoutConstraint(item: bannerView, attribute: .bottom, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0), NSLayoutConstraint(item: bannerView, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1, constant: 0) ]) } /// Tells the delegate an ad request loaded an ad. func adViewDidReceiveAd(_ bannerView: GADBannerView) { print("adViewDidReceiveAd") } /// Tells the delegate an ad request failed. func adView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: GADRequestError) { print("adView:didFailToReceiveAdWithError: \(error.localizedDescription)") } /// Tells the delegate that a full-screen view will be presented in response /// to the user clicking on an ad. func adViewWillPresentScreen(_ bannerView: GADBannerView) { print("adViewWillPresentScreen") } /// Tells the delegate that the full-screen view will be dismissed. func adViewWillDismissScreen(_ bannerView: GADBannerView) { print("adViewWillDismissScreen") } /// Tells the delegate that the full-screen view has been dismissed. func adViewDidDismissScreen(_ bannerView: GADBannerView) { print("adViewDidDismissScreen") } /// Tells the delegate that a user click will open another app (such as /// the App Store), backgrounding the current app. func adViewWillLeaveApplication(_ bannerView: GADBannerView) { print("adViewWillLeaveApplication") } let adSize = GADAdSizeFromCGSize(CGSize(width: 300, height: 50)) }
额外的优化提示
- 我把约束里的
bottomLayoutGuide换成了view.safeAreaLayoutGuide,这是iOS 11+更安全的布局方式,避免广告被底部刘海遮挡 - 确保你已经在
Info.plist里正确配置了AdMob的应用ID(GADApplicationIdentifier),这也是容易忽略的坑点
内容的提问来源于stack exchange,提问作者Fletcher
相关产品推荐
相关产品推荐

