1

I have a banner view and want to have a custom close button. My problem is that the button is displayed before the ad is loaded and displayed.

class RootVC: UIViewController, GADBannerViewDelegate {

    var googleAdBanner: GADBannerView!
    var googleBannerCloseBtn: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        googleAdBanner = GADBannerView(frame:CGRectMake(0,0,100,100))
        googleAdBanner.center = CGPointMake(self.view.bounds.size.width  / 2, self.view.bounds.size.height / 2)
        googleAdBanner.adUnitID = "xx"
        googleAdBanner.rootViewController = self
        googleAdBanner.loadRequest(GADRequest())
        adViewWillPresentScreen(googleAdBanner)
        googleAdBanner.delegate = self
        self.view.addSubview(googleAdBanner)
    }

    func adViewWillPresentScreen(bannerView: GADBannerView!) {
        googleBannerCloseBtn = UIButton(frame: CGRectMake( 5 , 5, 25, 25))
        googleBannerCloseBtn.backgroundColor = UIColor.clearColor()
        googleBannerCloseBtn.setImage(UIImage(named: "closeBtn"), forState: .Normal)
        googleBannerCloseBtn.setTitle("Click Me", forState: UIControlState.Normal)
        googleBannerCloseBtn.addTarget(self, action: #selector(RootVC.buttonAction(_:)), forControlEvents: UIControlEvents.TouchUpInside)
        googleBannerCloseBtn.tag = 1
        googleAdBanner.addSubview(googleBannerCloseBtn)
    }

How do I present the button only when the GADBannerView has loaded an ad and is presented?

Same behavior with adViewDidReceiveAd. The button is visible, even if the GADBannerView is "invisible" because there is no ad loaded currently.

Screens as requested. As you see, the button, that is a subView of the GADBannerView is displayed before the ad itself is displayed.

enter image description here enter image description here

Daniel Storm
  • 18,301
  • 9
  • 84
  • 152
David Seek
  • 16,783
  • 19
  • 105
  • 136
  • Could you add a screenshot to your question of what the close button looks like when added to your `GADBannerView`. Need a better idea of what you're describing. – Daniel Storm Sep 10 '16 at 13:25
  • @DanielStorm screens added – David Seek Sep 10 '16 at 13:41
  • I'm away from my computer atm but will look at this later. One more question. Did you want a full screen interstitial ad or a banner ad at the bottom of the view? Using a banner like how you are is a little unorthodox. An interstitial, `GADIntersitial`, is a full screen ad, usually pays more, and comes with its own close button. – Daniel Storm Sep 10 '16 at 13:51
  • okay, so you'd advice me to take that fullscreen banner? then i'll do so. and take my old banner with constant position on the bottom or so.... `GADIntersitial` will google it. but it would be nice, if you could still check on my issue – David Seek Sep 10 '16 at 13:53
  • especially thank you for the "pays more" point – David Seek Sep 10 '16 at 13:53
  • My pleasure. I'll work up an answer with examples for both situations at some point today for you. – Daniel Storm Sep 10 '16 at 13:55
  • looking forward to it – David Seek Sep 10 '16 at 13:55

1 Answers1

2

I've commented out alot of the logic in this example. The only thing that I didn't mention was that you will need to create two Ad Unit ID's. One for your GADBannerView and one for your GADInterstitial on AdMob.com.

import UIKit
import GoogleMobileAds // Import AdMob

class ViewController: UIViewController, GADBannerViewDelegate, GADInterstitialDelegate { // Include our delegates

    // Create our ads
    var banner = GADBannerView(adSize: kGADAdSizeBanner) // kGADAdSizeBanner is a default banner size
    var interstitial = GADInterstitial(adUnitID: "YourInterstitialAdUnitID")

    override func viewDidLoad() {
        super.viewDidLoad()
        // View has loaded so lets setup our ads initially
        setupAds()
    }


    // MARK: - Setup Ads
    func setupAds() {
        // Setup our banner ad
        banner.adUnitID = "YourBannerAdUnitID"
        banner.rootViewController = self
        banner.delegate = self
        // Hide our banner initially until it loads an ad
        // Not doing this is why your close button was visible
        // GADBannerView's with no ad are essentially "clear", not hidden
        banner.alpha = 0.0
        banner.loadRequest(GADRequest())
        // Position banner on bottom of view
        banner.frame = CGRect(x: 0.0,
                              y: view.frame.height - banner.frame.height,
                              width: view.frame.width,
                              height: banner.frame.height)
        // Create your button here and add it as a subview to banner
        // banner.addSubview(closeButton)
        view.addSubview(banner)

        // Setup our interstitial ad initially
        interstitial.delegate = self
        interstitial.loadRequest(GADRequest())
    }


    // MARK: - Load Interstitial Ad
    func loadFullScreenAd() {
        // GADInterstitial's are single use. You have to create a new GADInterstitial for each presentation
        // So, if you'd like to show more than one GADInterstitial in your apps session we need this
        // This func will be used to create a new GADInterstitial after one has been displayed and dismissed
        interstitial = GADInterstitial(adUnitID: "YourInterstitialAdUnitID")
        interstitial.delegate = self
        interstitial.loadRequest(GADRequest())
    }


    // MARK: - Show Interstitial Ad
    func showFullScreenAd() {
        // Call this function when you want to present the interstitial ad
        // ie. game over, transition to another vc, etc...
        // Make sure you give atleast a few seconds for this ad to load before atempting to present it
        // For example, don't try to present this ad in viewDidAppear

        // Check if the interstitial ad is loaded before trying to present it
        if interstitial.isReady {
            interstitial.presentFromRootViewController(self)
        }
    }


    // MARK: - Close Button Action
    func closeButtonAction() {
        // This is where we will handle your close button that you've added to your GADBannerView
        // You can handle this two ways and it depends on what you'd like to do
        // If you don't want to show the banner ad again during the entire app session you would hide the banner
        // This way even if we change the alpha values in our delegate methods the banner will remain hidden
        banner.hidden = true

        // Another way you can handle the close button would be to hide the banner until another banner ad is loaded
        // I believe the refresh rate for banner ads is 45-60 seconds. You can customize the refresh time on AdMob.com
        // So, this way if the user tapped the close button the banner would fade out
        // But, when another banner ad is loaded the banner would fade back in because of the code in our adViewDidReceiveAd delegate method
        UIView.animateWithDuration(0.2) {
            self.banner.alpha = 0.0
        }

        /////* Choose which way you'd like to handle the close button and remove the code for the other */////
    }


    // MARK: - GADBannerView Delegate Methods
    func adViewDidReceiveAd(bannerView: GADBannerView!) {
        print("adViewDidReceiveAd")
        // We received an ad so lets show it
        // You could even fade in the banner if you'd like
        UIView.animateWithDuration(0.2) { 
            self.banner.alpha = 1.0
        }
    }

    func adView(bannerView: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
        print("banner didFailToReceiveAdWithError: \(error)")
        // We received an error when trying to load our GADBannerView
        // Lets hide it because we don't have an ad
        // You could also fade this out if you'd like
        UIView.animateWithDuration(0.2) {
            self.banner.alpha = 0.0
        }
    }


    // MARK: - GADInterstitial Delegate Methods
    func interstitialDidReceiveAd(ad: GADInterstitial!) {
        print("interstitialDidReceiveAd")
    }

    func interstitialWillPresentScreen(ad: GADInterstitial!) {
        print("interstitialWillPresentScreen")
        // If you needed to pause anything in your app this would be the place to do it
        // ie. sounds, game state, etc...
    }

    func interstitialDidDismissScreen(ad: GADInterstitial!) {
        print("interstitialDidDismissScreen")
        // The GADInterstitial has been shown and dismissed by the user
        // Lets load another one for the next time we want to show a GADInterstitial
        loadFullScreenAd()

        // If you paused anything in the interstitialWillPresentScreen delegate method this is where you would resume it
    }

    func interstitial(ad: GADInterstitial!, didFailToReceiveAdWithError error: GADRequestError!) {
        print("interstitial didFailToReceiveAdWithError: \(error)")
    }
}

Also, if you plan on presenting the GADInterstitial often in your application I'd recommend disabling video ads on AdMob.com for that Ad Unit ID. AdMob interstitial video ads disable the close button for 5 seconds, kind of like the skip button on YouTube, and will aggravate your users instantaneously. If you're rarely showing the GADInterstitial then I'd leave the video ads enabled.

enter image description here

Daniel Storm
  • 18,301
  • 9
  • 84
  • 152
  • thank you so much for your effort. one follow up question, i'm getting: `NSLocalizedFailureReason=Request Error: No ad to show` – David Seek Sep 11 '16 at 01:56
  • i'm getting it on the interstitial, my app unit id for the interstitial is for sure correct. i've created one w/o video as you recommended – David Seek Sep 11 '16 at 01:57
  • according to this http://stackoverflow.com/questions/25642492/dfp-issue-no-ad-to-show it might be because width/height is 0 . possible issue? – David Seek Sep 11 '16 at 01:57
  • `interstitial didFailToReceiveAdWithError: Error Domain=com.google.ads Code=1 "Request Error: No ad to show." UserInfo={NSLocalizedDescription=Request Error: No ad to show., NSLocalizedFailureReason=Request Error: No ad to show.} adViewDidReceiveAd` – David Seek Sep 11 '16 at 02:06
  • the banner is displayed properly, but the interstitial throws the error. so i guess my app id is not blacklisted (as in some google threads suggested to check) – David Seek Sep 11 '16 at 02:11
  • @DavidSeek if you just created the Ad Unit ID for your interstitial it can take up to 24 hours before it starts delivering ads. – Daniel Storm Sep 11 '16 at 02:20
  • i see. thank you for your continuing support! i'll check by tomorrow again then – David Seek Sep 11 '16 at 02:29
  • ps. i have tested it now with a testAdID from the google docs. i'm now getting `interstitialDidReceiveAd`, but there is no ad displayed. i'm testing the ad within a "rootViewController", subclass of UINavigationController... may that be the issue? `interstitial.presentFromRootViewController(self)` – David Seek Sep 11 '16 at 02:31
  • @DavidSeek sounds like it. Instead of `self` use your root vc. – Daniel Storm Sep 11 '16 at 02:35
  • found the mistake... `showFullScreenAd()` was never called ^^ did put it inside `interstitialDidReceiveAd` – David Seek Sep 11 '16 at 03:52
  • thank you also for implementing my wish with the close button... hope you're getting so much more up votes for this. works awesome – David Seek Sep 11 '16 at 04:03