AdMob GADBannerView not releasing and receiving ad requests when it shouldn't - uiview

Here is my problem.
Also please not that I am aware of AdWhirl but choose not to use it because I prefer to have control over what is happening with my ads.
Basically I have iAds and AdMob. I start out always with iAds and if the ads have nothing to show I initialize AdMob and start showing it. Then when iAds finally gets something to show I hide Admob ads and destroy the view and display the iAds again.
This seems to work for 1 iteration meaning :
initialize iAds
iAds have no content to show
hide iAds
initialize Admob
Admob displays ads
iAds have received content so we should display it!
hide Admob
release the Admob view object
The problem is.. over time if I leave the app running and iAd fails to load ads a few times (meaning I do a bit of switching which results in creating Admob views) the released Admob view object is not being released and keeps receiving new ads even though it shouldn't.
Here is the code that I run whenever I receive a code 3 from iAds (meaning :The operation couldn’t be completed. Ad inventory unavailable)
-(void) smartInitialize:(UIViewController*) theVC
{
NSLog(#"AMOB :: smartInitialize");
if(!initialized)
{
NSLog(#"AMOB :: PRE initialization");
CGRect appFrame = [UIScreen mainScreen].applicationFrame;
UIView * theView = [[UIView alloc] initWithFrame:appFrame];
theView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
theViewController = theVC;
//[theViewController retain];
self.view = theView;
[theView release];
adMobAd = nil;
adMobAd = [self requestNewAdmobView];
if(adMobAd != nil)
{
NSLog(#"AMOB :: adding ADMOBVIEW TO VIEW CONTROLLER!");
[theVC.view addSubview:adMobAd];
[adMobAd release];
}
initialized = YES;
}
else
{
NSLog(#"AMOB :: POST initialization");
if(adMobAd!=nil)
{
NSLog(#"AMOB :: adMobView is present, doing nothing...");
}
else
{
NSLog(#"AMOB :: reinitializing..");
[self reinitializeAdmob];
}
}
}
Here is the [self requestNewAdmobView] function :
- (GADBannerView*) requestNewAdmobView
{
NSLog(#"AMOB :: requestNewAdmobView");
CGRect adFrame = CGRectZero;
NSString * appID = nil;
adMobAd = nil;
if(DEVICE_IPAD)
{
adFrame.size = GAD_SIZE_728x90;
appID = #"id1";
}
else
{
adFrame.size = GAD_SIZE_320x50;
appID = #"id2";
}
GADBannerView * tmp = nil;
tmp = [[GADBannerView alloc] initWithFrame:adFrame];
if(tmp != nil)
{
NSLog(#"AMOB :: adMobAD != nil , commencing with other stuff!");
tmp.adUnitID = appID;
tmp.rootViewController = gD.viewController;
tmp.delegate = self;
[tmp loadRequest:[GADRequest request]];
[tmp setHidden:NO];
}
else
{
NSLog(#"AMOB :: adMobAD == nil , THIS IS BAD..");
}
return tmp;
}
Here is the [self reinitializeAdmob] function :
-(void) reinitializeAdmob
{
NSLog(#"AMOB :: reinitializeAdmob");
if(theViewController != nil)
{
[self shutdownAdmob];
adMobAd = nil;
adMobAd = [self requestNewAdmobView];
if(adMobAd!=nil)
{
[theViewController.view addSubview:adMobAd];
}
}
}
And finally the [self shutdownAdmob]
-(void) shutdownAdmob
{
NSLog(#"AMOB :: shutdownAdmob");
if(adMobAd!=nil)
{
NSLog(#"AMOB :: adMobAd != nil, removing from superview and nilling...");
adMobAd.delegate = nil;
[adMobAd removeFromSuperview];
//[adMobAd release];
adMobAd = nil;
}
else
{
NSLog(#"AMOB :: adMobAd == nil");
}
}
Now from what I understand I am cleaning the GADBannerView called AdMobView correctly because :
at first it is == nil
then in [self requestNewAdmobView] i am allocing an instance so retain count = 1
I am returning it and then adding it to the viewControllers view and the view retains it so that makes the retain count go up to 2
I am then releasing the adMobView so I no longer own it and the retain drops down to 1
then when I want to get rid of the object completely in [self shutdownAdmob] i use the removeFromSupreview function which releases the view from the controller and thus it should dealloc it (I even tested this by subclassing the GADViewController and doing an NSLog upon deallocation and it does indeed dealloc).
Phew.. That's a lot of text sorry for that. So the question is :
why does the admobview remove itself correctly the 1st time but durring the 2nd time it does not.?

You must release the adMobAd in shutdownAdMob.
The removeFromSuperview decreases the reference count of the adMobAd, but
the count was incremented with addSubView, so you must release it.

I've had the same problem. I solved it by selecting this check

Related

Getting an error with Interstitial Ads (iAd and Spritekit)

I keep getting an error within this section of code:
// Interstitial iAd
-(void)showFullScreenAd {
// Check if already requesting ad
if (requestingAd == NO) {
interstitial = [[ADInterstitialAd alloc] init];
interstitial.delegate = self;
self.interstitialPresentationPolicy = ADInterstitialPresentationPolicyManual;
[self requestInterstitialAdPresentation];
NSLog(#"interstitialAdREQUEST");
requestingAd = YES;
}
}
-(void)interstitialAd:(ADInterstitialAd *)interstitialAd didFailWithError:(NSError *)error {
interstitial = nil;
requestingAd = NO;
NSLog(#"interstitialAd didFailWithERROR");
NSLog(#"%#", error);
}
-(void)interstitialAdDidLoad:(ADInterstitialAd *)interstitialAd {
NSLog(#"interstitialAdDidLOAD");
if (interstitialAd != nil && interstitial != nil && requestingAd == YES) {
//[interstitial presentFromViewController:self];
//[interstitial presentInView:self.view] // I get an error on this line
NSLog(#"interstitialAdDidPRESENT");
if (interstitial.loaded) {
[self requestInterstitialAdPresentation]; //I also get an error on this line too
}
}
}
-(void)interstitialAdDidUnload:(ADInterstitialAd *)interstitialAd {
interstitial = nil;
requestingAd = NO;
NSLog(#"interstitialAdDidUNLOAD");
}
-(void)interstitialAdActionDidFinish:(ADInterstitialAd *)interstitialAd {
interstitial = nil;
requestingAd = NO;
NSLog(#"interstitialAdDidFINISH");
}
Its something to do with this particular line:
[self requestInterstitialAdPresentation];
This is the error I'm getting and I have no idea what this line needs changing to so that the error stops:
-[UIView setShowsFPS:]: unrecognized selector sent to instance 0x146e241a0
Ive gotten this error in the past when working with the same sort of code, it usually appears when I start trying to implement interstitial ads. I seem to be having a lot of trouble trying to implement interstitial ads and I have read a lot of tutorials. I have no idea what I'm doing wrong :( can someone please help?
Regards,
Ryan
setShowsFPS: is a method on SKView, but not on UIView.
Although I don't see the cause in the code you posted, the error means that a UIView instance is being passed to a method that expects an SKView. Set an exception breakpoint to try to figure out where. It's possible that it isn't your code that's triggering the call.

APNS to open a certain part of an application

I've just implemented a commenting feature in my app. Ideally when someone leaves a comment, I'd like all notified people be able to swipe the push notification and open the app on that post.
I assume you want to open the concerned page directly. There are many ways to go about this, and it depends on how your app is laid out.
If you want to open an inner page upon app launch, you can programmatically trigger the segues that the user would otherwise need to make manually. (this ensures the back/home buttons work as opposed to loading the desired page directly).
Here's an excerpt from one of my own code, your use case may not be the same, but this is all i can do unless you give us more details.
- (BOOL) navigateToRespectiveSectionforPushNot:(NSDictionary*)pushNot
{
id rootVC = self.window.rootViewController;
NSLog(#"ROOT CLASS : %#", [rootVC class]);
if ([rootVC isKindOfClass:[SWRevealViewController class]])
{
NSLog(#"Root Class looking good... mission Navigate!!");
SWRevealViewController *homeVC = (SWRevealViewController*) rootVC;
NSString *category = [[pushNot objectForKey:pushPayloadKeyaps] objectForKey:pushPayloadKeyCategory];
NSString *subCat = [[pushNot objectForKey:pushPayloadKeyaps] objectForKey:pushPayloadKeySubCategory];
NSLog(#"category : %# , subcat : %#",category,subCat);
//The code for the page to which i'm supposed to navigate to is contained in the push notification payload
if ([category isEqualToString:pushCategoryItemChat])
{
[homeVC.rearViewController performSegueWithIdentifier:#"chatPush" sender:nil];
UINavigationController *nc = (UINavigationController*)homeVC.frontViewController;
NSLog(#"FrontView Class : %#",[nc.viewControllers[0] class]);
UITableViewController *tvc = (UITableViewController*)nc.viewControllers[0];
NSDictionary *send = #{chatPushTargetUserId:subCat,chatPushTargetUserName:#"",chatPushTargetUserImage:#""};
[tvc performSegueWithIdentifier:#"seguePushDemoVC" sender:send];
return YES;
}
//communityPush historyPush
else if ([category isEqualToString:pushCategoryItemCommunity])
{
if ([subCat isEqualToString:pushSubCatItemNewRequest])
{
[homeVC.rearViewController performSegueWithIdentifier:#"communityPush" sender:nil];
return YES;
}
else if ([subCat isEqualToString:pushSubCatItemAccepted])
{
[homeVC.rearViewController performSegueWithIdentifier:#"communityPush" sender:nil];
return YES;
}
}
else if ([category isEqualToString:pushCategoryItemHistory])
{
[homeVC.rearViewController performSegueWithIdentifier:#"historyPush" sender:nil];
return YES;
}
}
else
{
UIAlertView *whoa = [[UIAlertView alloc] initWithTitle:#"WHOA!!" message:#" That wasn't supposed to happen. You are not even logged in. Call 911..." delegate:nil cancelButtonTitle:#"mmKay.." otherButtonTitles:nil, nil];
[whoa show];
}
return NO;
}
I hope the code is self explanatory. cheers

iOS: Add Interstitial Ad when performing a segue to a new viewController?

I want to show an Interstitial Ad (from iAd framework) imediately after performing a segue between viewControllers in the storyboard.
I tried to launch [interstitial presentInView:view] (as stated in Apple Documentation) but the ad is not showing.
Any help?
Finally, I managed to solve my doubt.
- (void) showFullScreenAd {
if (requestingAd == NO) {
interstitial = [[ADInterstitialAd alloc] init];
interstitial.delegate = self;
self.interstitialPresentationPolicy = ADInterstitialPresentationPolicyManual;
[self requestInterstitialAdPresentation];
NSLog(#"interstitialAdREQUEST");
requestingAd = YES;
}
}
-(void) interstitialAdDidLoad:(ADInterstitialAd *)interstitialAd{
NSLog(#"interstitialAd DidLOAD");
if (interstitialAd != nil && interstitial != nil && requestingAd == YES) {
NSLog(#"interstitialDidPRESENT");
[interstitial presentFromViewController:self];
}
}

Game Center Sandbox mode display multiple leaderboards

I'm preparing to launch my first app and want to have multiple leaderboards inside my game. Currently in sandbox mode I can track and log scores into Game Center successfully. Game Center saves my scores (only if it is higher) and seems to be fully functional.
I know through Itunes Connect we have the ability to set up multiple leaderboards and it seems pretty straight forward. I still want to be able to test multiple leaderboards before publishing my game though. Is there a way to do this in sandbox mode? Currently it seems like my scores are only automatically logged into a default leaderboard. Below is the relevant code I'm using to save/access scores. Thanks!
ABGameKitHelper.m
#pragma mark - Leaderboard
-(void) reportScore:(long long)aScore forLeaderboard:(NSString*)leaderboardId
{
GKScore *score = [[GKScore alloc] initWithCategory:leaderboardId];
score.value = aScore;
[score reportScoreWithCompletionHandler:^(NSError *error) {
if (!error)
{
if(![self hasConnectivity])
{
[self cacheScore:score];
}
if (ABGAMEKITHELPER_LOGGING) NSLog(#"ABGameKitHelper: Reported score (%lli) to %# successfully.", score.value, leaderboardId);
}
else
{
[self cacheScore:score];
if (ABGAMEKITHELPER_LOGGING) NSLog(#"ABGameKitHelper: ERROR -> Reporting score (%lli) to %# failed, caching...", score.value, leaderboardId);
}
}];
}
-(void) showLeaderboard:(NSString*)leaderboardId
{
GKLeaderboardViewController *viewController = [GKLeaderboardViewController new];
viewController.leaderboardDelegate = self;
if (leaderboardId)
{
viewController.category = leaderboardId;
CCLOG(#"Going to category already created");
}
[[self topViewController] presentViewController:viewController animated:YES completion:nil];
}
MainScene.m
- (void)gameCenter {
[[ABGameKitHelper sharedHelper] reportScore:1400 forLeaderboard:#"Score"];
[[ABGameKitHelper sharedHelper] showLeaderboard:#"Score"];
}
I'm not sure if I understand your question properly, but I'll try to answer! Game Center does support multiple leaderboards:
-If you want to send a score to specific leaderboard, you just have to call the function [[ABGameKitHelper sharedHelper] reportScore:X forLeaderboard:LEADERBOARD_ID];, where X represents the score you'd like to send, and LEADERBOARD_ID is the ID of the leaderboard you want to send the score to, as specified in iTunes Connect.
-When you have multiple leaderboards, if you don't want to show just one leaderboard, but a list of them all, you should use the GKGameCenterViewController class instead. However, be careful; this ViewController has been added in iOS 6 only, so you must check which version the device is running. I am also using the ABGameKitHelper, so I've made a function to show this kind of view. Here it goes :
ABGameKitHelper.m
- (void) showGameCenter{
if (![[ABGameKitHelper sharedHelper] hasConnectivity]) return;
//Check if device runs on iOS 5
if([[[UIDevice currentDevice]systemVersion]intValue]==5)
{
//If so, we must use the GKLeaderboardViewController
GKLeaderboardViewController *leaderboard = [[GKLeaderboardViewController alloc] init];
if (leaderboard != nil)
{
leaderboard.leaderboardDelegate = self;
[[self topViewController] presentViewController:leaderboard animated:YES completion:nil];
}
}else if ([[[UIDevice currentDevice]systemVersion]intValue]>=6)
{
//if it runs on iOS 6 or higher, we use GKGameCenterViewController
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
if (gameCenterController != nil)
{
gameCenterController.gameCenterDelegate = self;
gameCenterController.viewState = GKGameCenterViewControllerStateDefault;
[[self topViewController] presentViewController:gameCenterController animated:YES completion:nil];
}
}
}
And don't forget to add :
- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController{
[gameCenterViewController dismissViewControllerAnimated:YES completion:nil];
}
Using this function will allow you to show a nice view containing all your leaderboards and achievements.
Hope this helps!

When my application first launches, iAd refuses to load an ad on the first screen

When my application launches, iAd refuses to load an ad on the first screen. No error message, nothing. If I switch screens (going to another screen), it starts getting ads and serving them up, even when I go back to the first screen.
I am using a single iAd instance that is in the ApplicationDelegate. I am attempting to link in the iAdBanner in viewDidAppear, and unlink in viewWillDisappear.
The viewDidAppear method:
- (void)viewDidAppear:(BOOL)animated
{
NSLog(#"view did appear");
[super viewDidAppear:animated];
ADBannerView *adBanner = SharedAdBannerView;
adBanner.requiredContentSizeIdentifiers = (&ADBannerContentSizeIdentifierPortrait != nil) ?
[NSSet setWithObjects:ADBannerContentSizeIdentifierPortrait, ADBannerContentSizeIdentifierLandscape, nil] :
[NSSet setWithObjects:ADBannerContentSizeIdentifier320x50, ADBannerContentSizeIdentifier480x32, nil];
[self.view addSubview:adBanner];
// set the delegate to self, so that we are notified of ad responses
[adBanner setDelegate:self];
isAdShown = [adBanner isBannerLoaded];
[self layoutForCurrentOrientation:animated];
}
The layout method:
- (void)layoutForCurrentOrientation:(BOOL)animated
{
//TODO: this only handles bottom-located elements
ADBannerView *adBanner = SharedAdBannerView;
CGFloat animationDuration = animated ? 0.2f : 0.0f;
// by default content consumes the entire view area
CGRect contentFrame = contentView.bounds;
CGRect owningViewFrame = [self view].bounds;
// the banner still needs to be adjusted further, but this is a reasonable starting point
// the y value will need to be adjusted by the banner height to get the final position
CGPoint bannerOrigin = CGPointMake(CGRectGetMinX(owningViewFrame), CGRectGetMaxY(owningViewFrame));
CGFloat bannerHeight = 0.0f;
// First, setup the banner's content size and adjustment based on the current orientation
if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
adBanner.currentContentSizeIdentifier = (&ADBannerContentSizeIdentifierLandscape != nil) ? ADBannerContentSizeIdentifierLandscape : ADBannerContentSizeIdentifier480x32;
else
adBanner.currentContentSizeIdentifier = (&ADBannerContentSizeIdentifierPortrait != nil) ? ADBannerContentSizeIdentifierPortrait : ADBannerContentSizeIdentifier320x50;
bannerHeight = adBanner.bounds.size.height;
// Depending on if the banner has been loaded, we adjust the content frame and banner location
// to accomodate the ad being on or off screen.
// This layout is for an ad at the bottom of the view.
if (isAdShown)
{
NSLog(#"Banner is loaded");
contentFrame.size.height = owningViewFrame.size.height - bannerHeight;
bannerOrigin.y -= bannerHeight;
}
else
{
NSLog(#"Banner is not loaded");
bannerOrigin.y += bannerHeight;
contentFrame.size.height = owningViewFrame.size.height;
}
NSLog(#"Banner content Frame: (%f, %f), (%f, %f)", bannerOrigin.x, bannerOrigin.y, contentFrame.size.width, contentFrame.size.height);
// And finally animate the changes, running layout for the content view if required.
[UIView animateWithDuration:animationDuration
animations:^{
contentView.frame = contentFrame;
[contentView layoutIfNeeded];
adBanner.frame = CGRectMake(bannerOrigin.x, bannerOrigin.y, adBanner.frame.size.width, adBanner.frame.size.height);
}];
}
and the viewWillDisappear method:
-(void)viewWillDisappear:(BOOL)animated
{
NSLog(#"View will disappear");
[super viewWillDisappear:animated];
[self removeLinkToAdBanner:animated];
}
-(void)removeLinkToAdBanner:(BOOL)animated
{
ADBannerView *adBanner = SharedAdBannerView;
if ([adBanner delegate] == self) {
adBanner.delegate = nil;
[adBanner removeFromSuperview];
}
}
The real frustration was this was working in the simulator before I upgraded to xcode 4. I upgraded, and all of a sudden it has stopped working. Anyone else seen behavior like this? Any ideas what I can do to fix it? The behavior occurs in the simulator on all test versions of 4.x (4.0 through 4.3).
I have encountered the same problem, and the fix is in the AppDelegate's bannerViewDidLoadAd method. You need to call your showBanner method there in order for the ad to display initially.
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
[_currentController showBannerView:_bannerView animated:YES];
}
Please check the new iAdSuite sample codes where I took this out.
iAdSuite Sample Code Updated 10/31/11

Resources