【发布时间】:2016-02-20 17:08:59
【问题描述】:
在显示来自 admobs 的 GADInterstitial 后我遇到了问题。
我做的是:
- 使用 presentFromRootViewController 打开 GADInterstitial:
- 关闭它并将应用程序置于后台
- 等几分钟
- 再次打开应用
- 点击一个 UI 元素
现在应用程序因 SIGSEGV 错误而崩溃
objc_msgSend() 选择器名称:_setContentMargin:
。好像我的记忆有问题,是新安排的什么的。它似乎现在有一个新对象,并且它没有选择器的响应器。但它只发生在我打开 GADInterstitial 一次之后。如果我没有打开 GADInterstitial,它运行没有问题。
我像谷歌在示例中那样加载并显示插页式广告...我不知道发生了什么...
我有一个全局 UIViewController 来决定是否显示广告。如果没有,则直接将 contenViewController 包装为 ChildViewController。如果它必须显示广告,它的 childviewController 将是一个“AdViewContoller”。这会将内容包装为 ChildViewController:
所以我有以下结构:
- RootViewController -> AdViewController -> ContentViewController
这是我的 AdViewController:
import UIKit
import GoogleMobileAds
let kAD_UNIT_ID_BANNER_AD: String = "ca-app-pub-3940256099942544/2934735716"
let kAD_UNIT_ID_INTERSTITIAL_AD: String = "ca-app-pub-3940256099942544/4411468910"
let kVIEW_CONTROLLER_ALLOWS_TO_SHOW_INTERSTITIAL_NOTIFICATION: String = "kviewcontrollerallowstoshowinterstitialnotification"
class AdViewController: UIViewController, GADBannerViewDelegate {
var childController: UIViewController? {
didSet {
if self.childController != nil {
self.addChildViewController(self.childController!)
}
}
}
var contentView: UIView = UIView()
var adLayoutConstraint: NSLayoutConstraint?
let adView: UIView = UIView();
let gadAdView: GADBannerView = GADBannerView(adSize: kGADAdSizeSmartBannerPortrait)
var intAdView: GADInterstitial?
override func viewDidLoad() {
super.viewDidLoad()
if self.childController != nil {
self.view.addSubview(self.childController!.view)
self.contentView = self.childController!.view
self.contentView.translatesAutoresizingMaskIntoConstraints = false
}
self.view.addSubview(self.adView)
self.adView.translatesAutoresizingMaskIntoConstraints = false
self.adView.backgroundColor = UIColor.blackColor()
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[content]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["content":self.contentView]))
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[ad]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["ad":self.adView]))
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[content][ad]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["ad":self.adView, "content":self.contentView]))
self.adLayoutConstraint = NSLayoutConstraint(item: self.adView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 50
)
self.adView.addConstraint(self.adLayoutConstraint!)
self.adView.addSubview(self.gadAdView)
self.gadAdView.translatesAutoresizingMaskIntoConstraints = false
self.adView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[gad]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["gad":self.gadAdView]))
self.adView.addConstraint(NSLayoutConstraint(item: self.gadAdView, attribute: .CenterX, relatedBy: .Equal, toItem: self.adView, attribute: .CenterX, multiplier: 1, constant: 0))
//self.adView.addConstraint(NSLayoutConstraint(item: self.gadAdView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 320))
gadAdView.adUnitID = kAD_UNIT_ID_BANNER_AD
gadAdView.rootViewController = self
gadAdView.loadRequest(GADRequest())
gadAdView.delegate = self
self.hideBanner()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "askedForInterstitial:", name: kVIEW_CONTROLLER_ALLOWS_TO_SHOW_INTERSTITIAL_NOTIFICATION, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "initInterstitial", name: UIApplicationDidBecomeActiveNotification, object: nil)
// Do any additional setup after loading the view.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
func hideBanner() -> Void {
self.adLayoutConstraint?.constant = 0
self.view.layoutIfNeeded()
}
func showBanner() -> Void {
self.adLayoutConstraint?.constant = 50
self.view.layoutIfNeeded()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func initInterstitial() -> Void {
print("UIApplicationDidBecomeActiveNotification called!")
self.intAdView = GADInterstitial(adUnitID: kAD_UNIT_ID_INTERSTITIAL_AD)
let request = GADRequest()
self.intAdView?.loadRequest(request)
}
init(subController: UIViewController) {
super.init(nibName: nil, bundle: nil)
self.childController = subController
self.addChildViewController(self.childController!)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func adViewDidReceiveAd(bannerView: GADBannerView!) {
self.showBanner()
}
func adView(bannerView: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
self.hideBanner()
}
func askedForInterstitial(notification:NSNotification) -> Void {
if notification.userInfo != nil {
if let c = notification.userInfo!["controller"] as? UIViewController {
self.showInterstitialInController(c)
} else {
self.showInterstitialInController(self)
}
} else {
self.showInterstitialInController(self)
}
}
class func presentInterstitial() -> Void {
AdViewController.presentInterstitialInController(nil)
}
class func presentInterstitialInController(c: UIViewController?) {
if c == nil {
NSNotificationCenter.defaultCenter().postNotificationName(kVIEW_CONTROLLER_ALLOWS_TO_SHOW_INTERSTITIAL_NOTIFICATION, object: nil)
}
else {
NSNotificationCenter.defaultCenter().postNotificationName(kVIEW_CONTROLLER_ALLOWS_TO_SHOW_INTERSTITIAL_NOTIFICATION, object: nil, userInfo: ["controller": c!])
}
}
private func showInterstitialInController(c: UIViewController) -> Void {
if self.intAdView != nil && self.intAdView!.isReady {
self.intAdView!.presentFromRootViewController(c)
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
这个控制器也有一个横幅。但当我试图向你展示我的整个过程时,我认为你也必须看到这一点。
我有这两个类函数presentInterstitial 和presentInterstitialInController,层次结构中的所有子视图控制器都可以要求显示插页式广告。这很好用,但正如我所说,问题接缝发生在应用程序在后台之后。
感谢您的帮助
阿图尔
【问题讨论】:
-
添加一些代码。比如你如何呈现或解雇或其他。
-
好吧...我的行不通...因为一个没人知道的原因:在
viewDidLoad的末尾,我添加了 ViewController 作为通知UIApplicationDidBecomeActiveNotification的观察者。如果我删除这条线,一切都会完美......