Search code examples
iosswiftsprite-kitiad

How to display iAd banner in different SpriteKit Scenes


I made simple game with Swift and SpriteKit. Everything seems to work but I have a problem with my iAd Setup. I only want to show the ad banner in specific scenes (main menu and game over) not during the gameplay. My iAd setup works but only if it is displayed all the time. My last attempt to fix it was with the NSNotificationCenter method. I have done it as I have seen it in other question/answers here but the app crashes immediately after launch. Hope that someone could help me. Just let me know if you need more of my code. Thanks in advance.

GameViewController.swift

class GameViewController: UIViewController, ADBannerViewDelegate {

var adBannerView = ADBannerView(frame: CGRect.zeroRect)

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleNotification", name: "hideAd", object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleNotification", name: "showAd", object: nil)

    self.adBannerView.delegate = self
    self.adBannerView.hidden = true
    adBannerView.center = CGPoint(x: adBannerView.center.x, y: view.bounds.size.height - adBannerView.frame.size.height / 2)
    view.addSubview(adBannerView)

    if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
        // Configure the view.
        let skView = self.view as SKView

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        var scene: SKScene = MainMenu(size: skView.bounds.size)
        scene.scaleMode = SKSceneScaleMode.AspectFill
        skView.presentScene(scene)
    }
}

func handleNotification(notification: NSNotification){
    if notification.name == "hideAd"{
        adBannerView.hidden = true
    }else if notification.name == "showAd"{
        adBannerView.hidden = false
    }
}

//iAD Setup
func bannerViewWillLoadAd(banner: ADBannerView!) {
    println("Ad loads")
}

func bannerViewDidLoadAd(banner: ADBannerView!){
    println("Ad loaded")
    self.adBannerView.hidden = false
}

func bannerViewActionDidFinish(banner: ADBannerView!) {
    println("resume scene")
    let skView = self.view as SKView
    skView.paused = false
}

func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
    println("pause scene")
    let skView = self.view as SKView
    skView.paused = true
    return true
}

func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
    println("Failed to load ad")
    self.adBannerView.hidden = true
}   more code.... 

MainMenu.swift

class MainMenu: SKScene{

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override init(size:CGSize){
    super.init(size: size)

    NSNotificationCenter.defaultCenter().postNotificationName("showAd", object: nil)
more code...

Solution

  • This works for me

    In my view controller I have this code:

    // Banner Ad

    var SH = UIScreen.mainScreen().bounds.height
    let transition = SKTransition.fadeWithDuration(1) 
    var UIiAd: ADBannerView = ADBannerView()
    
    override func viewWillAppear(animated: Bool) {
        var BV = UIiAd.bounds.height
        UIiAd.delegate = self
        UIiAd.frame = CGRectMake(0, SH + BV, 0, 0)
        self.view.addSubview(UIiAd)
    }
    
    override func viewWillDisappear(animated: Bool) {
        UIiAd.delegate = nil
        UIiAd.removeFromSuperview()
    }
    
    func bannerViewDidLoadAd(banner: ADBannerView!) {
        var BV = UIiAd.bounds.height
        UIView.beginAnimations(nil, context: nil)
        UIView.setAnimationDuration(1) // Time it takes the animation to complete
        UIiAd.alpha = 1 // Fade in the animation
        UIView.commitAnimations()
    }
    
    func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
        UIView.beginAnimations(nil, context: nil)
        UIView.setAnimationDuration(1)
        UIiAd.alpha = 0
        UIView.commitAnimations()
    }
    
    func showBannerAd() {
        UIiAd.hidden = false
        var BV = UIiAd.bounds.height
    
        UIView.beginAnimations(nil, context: nil)
        UIView.setAnimationDuration(1) // Time it takes the animation to complete
        UIiAd.frame = CGRectMake(0, SH - BV, 0, 0) // End position of the animation
        UIView.commitAnimations()
    }
    
    func hideBannerAd() {
        UIiAd.hidden = true
        var BV = UIiAd.bounds.height
    
        UIView.beginAnimations(nil, context: nil)
        UIView.setAnimationDuration(1) // Time it takes the animation to complete
        UIiAd.frame = CGRectMake(0, SH + BV, 0, 0) // End position of the animation
        UIView.commitAnimations()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.UIiAd.hidden = true
        self.UIiAd.alpha = 0
    
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "hideBannerAd", name: "hideadsID", object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "showBannerAd", name: "showadsID", object: nil)
    
    
        let scene = GameScene()
        // Configure the view.
        let skView = self.view as SKView
        skView.showsFPS = false
        skView.showsNodeCount = false
    
        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true
    
        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .AspectFit
        scene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        scene.size = skView.bounds.size
        skView.presentScene(scene, transition: transition)
    }
    

    To display it in the scene I want (for me it's the GameOver scene) I did this:

    override func didMoveToView(view: SKView) {
    
        showAds()
        // Rest of your code here...
    }
    
    func showAds(){
        NSNotificationCenter.defaultCenter().postNotificationName("showadsID", object: nil)
    }
    

    Basically this code creates a banner off the scene, and when the banner is loaded and the scene gets called, it slides up from the bottom. When you switch scenes, it offsets it again and when you come back to that scene, it slides up from the bottom again. If the banner doesn't load, it's off screen so no worries about it showing a white bar. Also, it sets the alpha to 0 if it doesn't load just in case (makes it invisible). Hope this helps.