lawicko
lawicko

Reputation: 7344

GADBannerView delegate methods not called if the view is not in the view hierarchy

I'm working with the Google Mobile Ads SDK on iOS and trying to display some ads. My code:

GADBannerView* bannerView = [[GADBannerView alloc] initWithAdSize:GADAdSizeFromCGSize(CGSizeMake(300, 250))];
bannerView.adUnitID = @"hidden";
bannerView.rootViewController = self;
bannerView.delegate = self;

GADRequest* request = [GADRequest request];
request.testDevices = @[ kGADSimulatorID ];

[bannerView loadRequest:request];

This works fine if I add the bannerView to the view hierarchy right after the code you see above. However, I don't really want to add it until the ad is loaded, so I wanted to delay it. I noticed that if the bannerView is not in the view hierarchy, the delegate methods are not called at all. Furthermore, I have found this answer, which is in line with what I'm observing. On the other hand, this is a quote from the GADBannerViewDelegate header:

/// Tells the delegate that an ad request successfully received an ad. The delegate may want to add
/// the banner view to the view hierarchy if it hasn't been added yet.
- (void)adViewDidReceiveAd:(GADBannerView *)bannerView;

This suggests that it should be possible to receive those delegate callbacks even if the view is not in the hierarchy, which is exactly what I want. So, any ideas how could I achieve this?

Upvotes: 4

Views: 4629

Answers (3)

Volker Voecking
Volker Voecking

Reputation: 5583

I just had the same issue after upgrading from the Admob SDK 7.56 to 8.2:

They changed the method names of the GADBannerViewDelegate protocol.
E.g. instead of

-(void)adViewDidReceiveAd:(GADBannerView *)adView;

it is now

-(void)bannerViewDidReceiveAd:(GADBannerView *)bannerView;

see also the migration guide to Admob SDK version 8:
https://developers.google.com/admob/ios/migration#methods_removedreplaced

Upvotes: 6

Daniel Storm
Daniel Storm

Reputation: 18898

You should add the GADBannerView to your view and set its hidden property to YES initially. Also, I'd suggest using the AdSize Constant kGADAdSizeBanner that AdMob provides. Here's a list of additional AdSize Constants.

For example:

bannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
bannerView.adUnitID = @"YourAdUnitID";
bannerView.rootViewController = self;
bannerView.delegate = self;
[bannerView loadRequest:[GADRequest request]];
bannerView.hidden = YES; // Hide banner initially
[self.view addSubview:bannerView];
// This will put the banner at the bottom of the screen and stretch to fit the screens width
[bannerView setFrame:CGRectMake(0, self.view.frame.size.height - bannerView.frame.size.height, self.view.frame.size.width, bannerView.frame.size.height)];

Then, when you receive an ad you unhide the banner. For example:

-(void)adViewDidReceiveAd:(GADBannerView *)adView {
    // We've received an ad so lets show the banner
    bannerView.hidden = NO;
    NSLog(@"adViewDidReceiveAd");
}

-(void)adView:(GADBannerView *)adView didFailToReceiveAdWithError:(GADRequestError *)error {
    // Failed to receive an ad from AdMob so lets hide the banner
    bannerView.hidden = YES;
    NSLog(@"adView:didFailToReceiveAdWithError: %@", [error localizedDescription]);
}

You could also animate this, if you'd prefer, by setting the banner's alpha property to 0.0 initially instead of using it's hidden property. Then, animate the alpha when you receive an ad. For example:

-(void)adViewDidReceiveAd:(GADBannerView *)adView {
    // We've received an ad so lets fade in the banner
    [UIView animateWithDuration:0.2 animations:^{
        bannerView.alpha = 1.0;
    }];
    NSLog(@"adViewDidReceiveAd");
}

-(void)adView:(GADBannerView *)adView didFailToReceiveAdWithError:(GADRequestError *)error {
    // Failed to receive an ad from AdMob so lets fade out the banner
    [UIView animateWithDuration:0.2 animations:^{
        bannerView.alpha = 0.0;
    }];
    NSLog(@"adView:didFailToReceiveAdWithError: %@", [error localizedDescription]);
}

Also, as a side note, the GADBannerView is transparent when there is no ad to display. So, adding it to your view and doing nothing else would work too.

Upvotes: 0

lawicko
lawicko

Reputation: 7344

Ok, so the problem here was that I didn't keep the reference to the bannerView. It was deallocated after the method returned, and this is why the delegate methods were not called.

Upvotes: 8

Related Questions