Search code examples
iosswiftiadadbannerview

Swift iAd - More than 10 instances of ADBannerView warning and CGAffineTransformInvert: singular matrix output


So I am trying to set up a simple iAd banner in my application but I am getting these two warnings in the output:

WARNING: More than 10 instances of ADBannerView or ADInterstitialView 
currently exist. This is a misuse of the iAd API, and ad performance will 
suffer as a result. This message is printed only once.

and

<Error>: CGAffineTransformInvert: singular matrix.

This is what I am using to implement my ADBannerView:

var adBannerView = ADBannerView()

func loadAds() {
    adBannerView = ADBannerView(frame: CGRect.zeroRect)
    adBannerView.center = CGPoint(x: adBannerView.center.x, y: view.bounds.size.height - adBannerView.frame.size.height / 2)
    adBannerView.delegate = self
    adBannerView.hidden = true
    view.addSubview(adBannerView)
}

//BannerView did load ad
func bannerViewDidLoadAd(banner: ADBannerView!) {
    adBannerView.hidden = false
}
//BannerView failed to load
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
    adBannerView.hidden = true
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    loadAds()
    //(rest of the code is from here onwards)

I tried adding this to stop the first error: (hasn't worked)

//BannerView will disappear
override func viewWillDisappear(animated: Bool) {
    adBannerView.removeFromSuperview()
    adBannerView.delegate = nil
}

Solution

  • The issue is every time you load your view you are creating a new instance of ADBannerView. What we need to do is create a ADBannerView once in our AppDelegate.swift and then present this ADBannerView on which ever views we would like to have an iAd banner. This is also called a Shared iAd Banner. In this example, I've created an ADBannerView in my AppDelegate.swift and then added it to my ViewController.swift's view.

    AppDelegate.swift

    import UIKit
    import iAd // Import iAd
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate, ADBannerViewDelegate { // Include the delegate for our banner
    
        var window: UIWindow?
        var adBannerView = ADBannerView() // Create our one ADBannerView
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Set delegate and hide banner initially
            adBannerView.delegate = self
            adBannerView.hidden = true
            return true
        }
    
        func bannerViewDidLoadAd(banner: ADBannerView!) {
            print("bannerViewDidLoadAd")
            adBannerView.hidden = false
        }
    
        func bannerViewActionDidFinish(banner: ADBannerView!) {
            print("bannerViewActionDidFinish")
        }
    
        func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
            print("didFailToReceiveAdWithError: \(error)")
            adBannerView.hidden = true
        }
    

    ViewController.swift

    import UIKit
    
    class ViewController: UIViewController {
    
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate // Create reference to our app delegate
    
        override func viewWillAppear(animated: Bool) {
            // Position
            appDelegate.adBannerView.center = CGPoint(x: view.frame.midX,
                y: view.frame.height - appDelegate.adBannerView.frame.height / 2)
            // Add to view
            view.addSubview(appDelegate.adBannerView)
        }
    

    Don't forget to remove the code from your viewWillDisappear(animated: Bool) function that you added previously. If you click on the banner and then dismiss it this function will be called and removing our banner from our view and setting our banners delegate equal to nil too soon will cause issues.