GADInterstitial presentFromRootViewController:应用程序从后台退出后导致崩溃

时间:2016-02-16 10:35:35

标签: ios crash

从admobs中显示GADInterstitial后出现问题。

我的工作是:

  1. 使用presentFromRootViewController打开GADInterstitial:
  2. 关闭它并将应用程序置于背景中
  3. 等几分钟
  4. 再次打开应用
  5. 点击UI元素
  6. 现在应用程序因 SIGSEGV错误而崩溃,原因为

      

    objc_msgSend()选择器名称:_setContentMargin:

    。它接缝我的记忆有一些问题,它是新的安排或什么的。它现在有一个新对象,它没有选择器的响应器。但它只发生在我打开一次GADInterstitial之后。如果我没有打开GADInterstitial,它会毫无问题地运行。

    我加载并在示例中显示像Google一样的插页式广告...我不知道会发生什么......

    我有一个全局的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.
        }
        */
    
    }
    

    此控制器也有横幅。但是当我试图告诉你我的整个过程时,我想你也必须看到它。 我有两个类函数presentInterstitialpresentInterstitialInController,所有hirarchy的childview控制器都可以要求显示插页式广告。这很好用,但正如我所说的那样,应用程序在后台运行后会出现问题。

    感谢您的帮助

    阿图尔

1 个答案:

答案 0 :(得分:0)

好的,我已经解决了......

问题不在于插页式广告,而是我为UIApplicationDidBecomeActiveNotification通知名称添加观察者的行:

我有一个功能:

func initInterstitial() -> Void {
    print("UIApplicationDidBecomeActiveNotification called!")
    self.intAdView = GADInterstitial(adUnitID: kAD_UNIT_ID_INTERSTITIAL_AD)
    let request = GADRequest()
    self.intAdView?.loadRequest(request)
}

我添加此功能作为

的观察者
NSNotificationCenter.defaultCenter().addObserver(self, selector: "initInterstitial", name: UIApplicationDidBecomeActiveNotification, object: nil)

第二次调用通知后,我的应用程序没有崩溃。

现在,如果我将该功能重命名为createInterstital

func createInterstitial() -> Void {
    print("UIApplicationDidBecomeActiveNotification called!")
    self.intAdView = GADInterstitial(adUnitID: kAD_UNIT_ID_INTERSTITIAL_AD)
    let request = GADRequest()
    self.intAdView?.loadRequest(request)
}

我添加了这样的观察者:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "createInterstitial", name: UIApplicationDidBecomeActiveNotification, object: nil)

所有作品都很完美......

我不知道为什么,但NotificationCenter似乎不喜欢使用init的函数。

希望这可以帮助一些人。

问候

阿图尔