RE: Creating A GADBannerView Singleton in AdMob Applications

1,850 views
Skip to first unread message

Brian Yager

unread,
May 24, 2012, 1:29:14 AM5/24/12
to google-adm...@googlegroups.com

In regards to Raj's post - http://googleadsdeveloper.blogspot.com/2012/04/creating-gadbannerview-singleton-in.html

We have attempted this singleton approach but there seems to be an issue somewhere.  Two days of trying to resolve without any luck.  Here is the scenario that causes a crash:

Using simulator targeting iOS 5.1 using the AdMob sdk 6.0.3:

Navigation Controller -> View Controller A -> View Controller B (loads Test Banner).  Clicking on banner presents the modal web view correctly.
Close View Controller B -> View Controller A (does not show ads).  -> Back to View Controller B (adds the previously-loaded Test Banner to the view).  Clicking on banner causes crash.

After further testing we noticed the following also causes a crash:

Navigation Controller -> View Controller A -> View Controller B (loads Test Banner).  No Click on banner.
Close View Controller B -> View Controller A (does not show ads).  -> Back to View Controller B (adds the previously-loaded Test Banner to the view).  Clicking on banner causes crash.

So it seems that the banner is continuing to send messages to viewcontrollers (set as the banner's rootviewcontroller) that have already been deallocated.

Here is screen grab of xcode crash if it helps: http://tinypic.com/r/68xzb4/6

In addition, I also noticed this in the console after the crash.  I don't know if it is related:

Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol OBJC_IVAR_$_UIViewController._storyboardSegueTemplates
Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol OBJC_IVAR_$_UIViewController._externalObjectsTableForViewLoading


Here is a pastebin of our singleton class: http://pastebin.com/EqtpchRx

....And in view controllers for which we wish to show banners:

//viewDidLoad
- (void)viewDidLoad {
    [super viewDidLoad];
    [[AdViewController sharedInstance] resetAdView:self];
    
}

//implementation of BannerViewDelegate
- (void)adViewDidReceiveAd:(GADBannerView *)bannerView {
    CGRect tmpFrame = bannerView.frame;
    tmpFrame.origin.y = 430.0;
    bannerView.frame = tmpFrame;
    [[self view] addSubview:bannerView];
}

Any assistance would be appreciated!

Raj Parameswaran

unread,
May 29, 2012, 8:11:31 PM5/29/12
to Google AdMob Ads Developers
Hey Brian,




That was a good find, there needs to be a tweak to the code to get it
to work properly I believe. The rootViewController of your adBanner
probably shouldn't be the rootViewController you pass in. Since you
are in a tabbed view, you want your rootViewController to be the
containing view controller that holds your UITabBarController.




One way of doing this is that when you're initializing your tabbed
view, you can initialize a property that holds the rootViewController
for your adBanner accordingly. Then, instead of a
setRootViewController method you'd want a setCurrentDelegate method
where you just change the current delegate and add the adBanner to the
view of the currentDelegate. I've sketched out some code below which
should work for your scenario I think:




In GADMasterViewController.h:




@property(nonatomic, assign) UIViewController<GADBannerViewDelegate>
    *currentDelegate;
@property(nonatomic, assign) UIViewController *adRootViewController;




In GADMasterViewController.m:




- (void)setCurrentDelegate:
    (UIViewController<GADBannerViewDelegate> *)newCurrentDelegate {
  // Reset the views if they pass in nil here.
  if ((!newCurrentDelegate) || (!self.adRootViewController)) {
    [bannerView_ removeFromSuperview];
    currentDelegate_ = nil;
    didReturnFromAdLandingPage_ = NO;
    didRequestAd_ = NO;
    return;
  }
  if (didReturnFromAdLandingPage_) {
    // Just have this so we don't unnecessarily add it into the view
everytime
    // the view is shown.
    didReturnFromAdLandingPage_ = NO;
    return;
  }
  if (!didRequestAd_) {
    bannerView_.rootViewController = self.adRootViewController;
    [bannerView_ loadRequest:[self createRequest]];
    didRequestAd_ = YES;
  }
  currentDelegate_ = newCurrentDelegate;
  [currentDelegate_.view addSubview:bannerView_];
}




So make sure you set the adRootViewController to the main container
view, not the view inside your tabbed view. Every time you switch tabs
then, you'd just set the current delegate to be the new 'inside' view.
Let me know how that works?

On May 23, 10:29 pm, Brian Yager <brianya...@gmail.com> wrote:
> In regards to Raj's post -http://googleadsdeveloper.blogspot.com/2012/04/creating-gadbannerview...
>
> We have attempted this singleton approach but there seems to be an issue
> somewhere.  Two days of trying to resolve without any luck.  Here is the
> scenario that causes a crash:
>
> Using simulator targeting iOS 5.1 using the AdMob sdk 6.0.3:
>
> Navigation Controller -> View Controller A -> View Controller B (loads Test
> Banner).  Clicking on banner presents the modal web view correctly.
> Close View Controller B -> View Controller A (does not show ads).  -> Back
> to View Controller B (adds the previously-loaded Test Banner to the view).
> Clicking on banner causes crash.
>
> After further testing we noticed the following also causes a crash:
>
> Navigation Controller -> View Controller A -> View Controller B (loads Test
> Banner).  No Click on banner.
> Close View Controller B -> View Controller A (does not show ads).  -> Back
> to View Controller B (adds the previously-loaded Test Banner to the view).
> Clicking on banner causes crash.
>
> So it seems that the banner is continuing to send messages to
> viewcontrollers (set as the banner's rootviewcontroller) that have already
> been deallocated.
>
> Here is screen grab of xcode crash if it helps:http://tinypic.com/r/68xzb4/6</>
>
> In addition, I also noticed this in the console after the crash.  I don't
> know if it is related:
>
> *Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol
> OBJC_IVAR_$_UIViewController._storyboardSegueTemplates
> Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol
> OBJC_IVAR_$_UIViewController._externalObjectsTableForViewLoading*

Touche Apps

unread,
Jun 5, 2012, 7:13:38 PM6/5/12
to Google AdMob Ads Developers
After trying a couple things i've found 2 different ways to fix the
crash.

In method of admob singleton

-(void)resetAdView:(UIViewController *)rootViewController

You can either replace
adBanner_.rootViewController = rootViewController;
with
adBanner_.rootViewController = [((AppDelegate *)[[UIApplication
sharedApplication] delegate]) navController]; (I have my navigation
controller set up in my appdelegate)

or what I believe to be a better fix is just adding this line in the
same method

if (isLoaded_) {
--- adBanner_.rootViewController = rootViewController; ---
[rootViewController.view addSubview:adBanner_];
} else {

adBanner_.delegate = self;
adBanner_.rootViewController = rootViewController;
adBanner_.adUnitID = kSampleAdUnitID;

Now when creating the AdMob ad in your View Controller B (VC-B) it
sets the rootViewController to VC-B. When you go back to VC-A or
navigation controller ad is already loaded and your rootViewController
of VC-B does not exist anymore.

Resetting the rootViewController to whichever view you're on has
worked for my app, not crashing anymore!

Hopefully i'm not too wrong :D

On Jun 5, 12:40 pm, Brian Yager <brianya...@gmail.com> wrote:
> Thanks Raj,
>
> We are using a UINavigationController, not a UITabBarController - but your
> suggestion would still apply.
>
> We have made it work with setting the rootViewController of the adBanner to
> the applications UINavigationController....
>
> I will test out your idea you suggested as well just to let you know if it
> works...
>
> Thanks
>
>
>
>
>
>
>
> On Thursday, May 24, 2012 12:29:14 AM UTC-5, Brian Yager wrote:
>
> > In regards to Raj's post -
> >http://googleadsdeveloper.blogspot.com/2012/04/creating-gadbannerview...
>
> > We have attempted this singleton approach but there seems to be an issue
> > somewhere.  Two days of trying to resolve without any luck.  Here is the
> > scenario that causes a crash:
>
> > Using simulator targeting iOS 5.1 using the AdMob sdk 6.0.3:
>
> > Navigation Controller -> View Controller A -> View Controller B (loads
> > Test Banner).  Clicking on banner presents the modal web view correctly.
> > Close View Controller B -> View Controller A (does not show ads).  -> Back
> > to View Controller B (adds the previously-loaded Test Banner to the view).
> > Clicking on banner causes crash.
>
> > After further testing we noticed the following also causes a crash:
>
> > Navigation Controller -> View Controller A -> View Controller B (loads
> > Test Banner).  No Click on banner.
> > Close View Controller B -> View Controller A (does not show ads).  -> Back
> > to View Controller B (adds the previously-loaded Test Banner to the view).
> > Clicking on banner causes crash.
>
> > So it seems that the banner is continuing to send messages to
> > viewcontrollers (set as the banner's rootviewcontroller) that have already
> > been deallocated.
>
> > Here is screen grab of xcode crash if it helps:
> >http://tinypic.com/r/68xzb4/6
>
> > In addition, I also noticed this in the console after the crash.  I don't
> > know if it is related:
>
> > *Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol
> > OBJC_IVAR_$_UIViewController._storyboardSegueTemplates
> > Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol
> > OBJC_IVAR_$_UIViewController._externalObjectsTableForViewLoading*

Rajkumar Parameswaran

unread,
Jun 14, 2012, 1:19:09 PM6/14/12
to google-adm...@googlegroups.com
I believe you're correct here. The thing that was crashing the initial singleton code was that it didn't take into account view controller hierarchies like tabbed controllers where the base view controller needs to be set to be the rootViewController for every view controller presented. Thanks for bringing up that issue and suggesting the fix.

Rajkumar Parameswaran

unread,
Jun 22, 2012, 8:18:54 PM6/22/12
to google-adm...@googlegroups.com
Hello,

I don't know if I completely understand the situation you're trying to explain here. Are you saying that you have View Controller A which you add the AdMob banner to (I presume you add it to View A), and then you present View B modally over this and add the banner to View B. Are you updating the root view controller to be View Controller B when you do this? (Or whatever View Controller controls View B)?

If this doesn't help you out, do you have some code you can perhaps show me that shows what you're trying to do?


On Wed, Jun 20, 2012 at 3:36 AM, jorcuscab <jorc...@yahoo.es> wrote:
Hello,

I have almost implement successfuly this Admob Singleton, altough I have a problem with it. I have managed to display the Admob (and iad) banners and the different views managed by different view controllers the application displays modally.

The problem that I have is that when an Admob banner is loaded into one view controller, if another is displayed modally, on clicking on the banner, the advertisement is not displayed on the new view. If I go back to the original view controller (dismissing the modal view), on clicking the banner, the advertisement is displayed correctly.

The same way, if I wait for a new banner to be loaded in the modal view, the advertisement is displayed correctly in the modal view on clicking such banner.

This only happens for AdMob banners and not for iAd.

Any hint you could provide to me to solve the problem?

Thanks in advance
Message has been deleted

Rajkumar Parameswaran

unread,
Oct 30, 2012, 12:35:17 PM10/30/12
to google-adm...@googlegroups.com
Are you using a UINavigationController or a UITabBarController to show all the views? Because if that's the case then you can just make that your rootViewController (so you don't have to change it).

SImilar to that question, is there some common parent view controller that you can set to be the rootViewController?

On Tue, Oct 30, 2012 at 7:05 AM, admober <victo...@gmail.com> wrote:
Hi Raj,

This issue is still there on 6.2.1 release. In most app, we need to keep the ad banner across views, especially over modal views. The current admob mediation doesn't seem to care the change of the rootviewcontroller property at all unless a new loadRequest is made. But making new requests between views changes will reduce the CTR and is not a good solution for the publisher.

This issue can easily be reproduced by
  1. create an adview and assign its rootviewcontroller
  2. call loadRequest and tap on the ad, it should work fine at this step
  3. present another modal view and move the adview into the new modal view and change the rootviewcontroller property to the modal view.
  4. now click the ad on the modal view and it just won't popup any fullscreen admob ads (iAd is working fine), and the status bar is blanked out.
  5. on step 4, if we make a loadRequest after the change of rootviewcontroller, then the ad banner works like step 2.

Could you please help?




--
 
 
 

Rajkumar Parameswaran

unread,
Oct 30, 2012, 2:35:38 PM10/30/12
to google-adm...@googlegroups.com
Hey,

Just trying to chase down this issue and see what it would take on our side to fix it. Can you check if the rootViewController is updated properly if you don't use mediation?

Raj

On Tue, Oct 30, 2012 at 9:49 AM, admober <victo...@gmail.com> wrote:
The problem is that in some apps with more complex navigation, there are more than 1 UINavigationControllers, or may using a modal view extensively. e.g. it presents an UIWebview to allow user browsing the web without leaving the app. In such case, the webview doesn't belong to the navigation controller and the fullscreen ad will just fail to response to clicks.

I read your blog at - http://googleadsdeveloper.blogspot.ca/2012/04/creating-gadbannerview-singleton-in.html and the resetAdView: doesn't change rootViewController at all if the adview is already created. So it will also fail when used against a modal view controller, or any one doesn't share with the original root when it's created.

--
 
 
 

Rajkumar Parameswaran

unread,
Oct 31, 2012, 2:22:07 PM10/31/12
to google-adm...@googlegroups.com
Thanks, it looks like this issue comes up because we make adapters set their ad view's rootViewController once when the ad is requested but don't change it whenever the rootViewController is changed.

I've filed a bug with our engineering team and can ping this thread once the issue gets looked at. In the meantime though, it looks like calling loadRequest: might be your best option to make sure the rootViewController is set properly.

On Tue, Oct 30, 2012 at 11:52 AM, admober <victo...@gmail.com> wrote:
Just did the test for multiple times and I can confirm that this issue only occurs when using mediation ID. When using the admob ID alone as the ad_unit_id, the rootViewController is updated properly and everything is working smooth.


On Tuesday, October 30, 2012 2:35:40 PM UTC-4, Raj Parameswaran wrote:
Hey,

Just trying to chase down this issue and see what it would take on our side to fix it. Can you check if the rootViewController is updated properly if you don't use mediation?

Raj

--
 
 
 

Message has been deleted

Rajkumar Parameswaran

unread,
Dec 4, 2012, 8:21:09 PM12/4/12
to google-adm...@googlegroups.com
@Bruno

1. Couldn't you just check your currentDelegate_ to make sure it's not nil before you forward any delegate notifications to it? Presumably if there's not viewController holding the GADBannerView you don't want anything receiving those notifications anyway?

2. Nope, if all you want to do is display the GADBannerView they don't need to support all of the methods from GADBannerViewProtocol.

3. For the white banner issue, what networks are you mediating with? Also are you using the latest adapters and version of the AdMob SDK if you are using mediation? We saw this issue with iAD previously but it should be fixed with the newest adapter.

@Victor

Are you doing anything special when you get the two adViewDidReceiveAd's? I think I saw this issue with Millennial before, but I thought it was fixed. Are you mediating and if so with what networks? 

On Mon, Dec 3, 2012 at 1:46 PM, Bruno Alvisio <bruno....@gmail.com> wrote:

Hello,

I think I am experiencing a similar problem with the Singleton as the ones described here. However, I am not sure I have impleted the code correctly. 

1. The application has a UINavagationController. Only in certain (not all) Viewcontrollers that get pushed into the UINavigationController I want to display banners.  In the viewWillAppear: method of all the viewControllers that I want the banner to show up, I call the method resetAdView:. However, I am having problems with the following escenario:

-       ViewController A: viewWillAppear: DOES NOT call resetAdView: (Banners are NOT showed in this view)

-       ViewController B: viewWillAppear: calls resetAdView: (Banners are showed.)


The following sequence of events happens:

è View Controller A pushed.

è View Controller B pushed

è View Controller B popped. (and deallocated)

In this case, the reference ‘currentDelegate_’ (in GADMasterViewController) still points to ViewController B. When adView:(GADBannerView *)view didFailToReceiveAdWithError: gets called I use the currentDelegate_ variable which causes my application to crash. (Isn’t currentDelegate_ a dangling pointer?)

Is there an error on how I am using the singleton? How can I solve this issue? One of the solutions I thought is to set the currentDelegate_ variable of the GADMasterViewController to nil everytime a ViewController dissapears.

 

2. I have a question about the adViewDidReceiveAd: method. If the only thing I need to do is to display the ad that the app receives (and I am calling resetAdView: in ViewWillAppear: of the viewController). Is there any reason I need to make the ViewControllers  still adhere to the GAD protocol and forward the notification?


3. Sometimes I am receiving ads but they are just empty (White Color). I was wondering if this issue is due to some error in my implementation.


Thank you. Bruno

--
 
 
 

Message has been deleted

Rajkumar Parameswaran

unread,
Dec 11, 2012, 12:49:03 PM12/11/12
to google-adm...@googlegroups.com
Hey Bruno,

If you're using ARC, you could probably make that currentDelegate a zeroing weak reference. In the case that your not, it sounds like a lot of unnecessary overhead to call resetAdView: again just to nil out the delegate. You may just want to make currentDelegate a property of the singleton and nil it out whenever your classes are being deallocated (assuming that the class being deallocated is the delegate).

Do any of these ways work better for you?

Raj

On Fri, Dec 7, 2012 at 1:08 PM, Bruno Alvisio <bruno....@gmail.com> wrote:

Hello Rajkumar,

 

Thank you for your answer.

1. Yes, I could check if the if currentDelegate_ is nil but in order for that approach to work, shouldn’t ‘[share resetAdView: nil]’ be called in the viewWillDissapear method of all the ViewControllers that display a banner? I am thinking of the situation that I have described in my previous post. If the app popped a viewController that displayed a delegate and the the current one didn’t support the display of ads, then currentDelegate_ will still be pointing to a ViewController that has been deallocated. Is this correct?


3. I am using AdMediation, The AdMob and iAd networks. I am using version 6.2.1. of the AdMob SDK. For he IAd adpater, the one released on October 4th.

Thank you,

Bruno

--
 
 
 

Message has been deleted

Rajkumar Parameswaran

unread,
Dec 13, 2012, 2:25:32 PM12/13/12
to google-adm...@googlegroups.com
Unfortunately there isn't a fix for this yet. I'll definitely update this thread once we have a fix in the SDK.

On Thu, Dec 13, 2012 at 1:10 AM, jorcuscab <jorc...@yahoo.es> wrote:
Hello,

I am back to iOS development after some months. Is there any news about this bug? I have tried with the latest version of the SDK and the problem still exist. As admober asked, could you please leave a note when a new version with the bug fix is out?

Thanks
--
 
 
 

Kartik Andalam

unread,
Sep 5, 2013, 1:53:48 AM9/5/13
to google-adm...@googlegroups.com
Hi Raj,
Has this issue been fixed?
Reply all
Reply to author
Forward
0 new messages