1

Following the Ray Wenderlich tutorial, I've incorporated the latest AdWhirl folders, deleted the adapters I'm not using, setup an account with iAd, uploaded a few house banners, configured the AdWhirl delivery and implemented the retrieve/display code in my Cocos2d app. My logs show that ads are being retrieved successfully but they do not appear on the screen. I'm thinking either they are displayed off screen (no man's land) or are hidden behind a CCLayer. Any suggestions for how to test/resolve this is much appreciated. It's a landscape only orientation if that helps.

Update: the RW tutorial is out of date for Cocos2d version 2.0 users...see below for the solution

Here is my AdWhirl code:

Library.h

#import "AdWhirlView.h"
#import "AdWhirlDelegateProtocol.h"
#import "RootViewController.h"
@interface Library : CCLayer <AdWhirlDelegate>{

this is what the tutorial said but is outdated

//RootViewController *viewController;

this is what is needed instead

UINavigationController *viewController

AdWhirlView *adWhirlView;
enum GameStatePP _state; }
@property(nonatomic,retain) AdWhirlView *adWhirlView; 
@property(nonatomic) enum GameStatePP state;

Library.mm

@implementation Library
@synthesize state = _state, adWhirlView;

In Init

self.state = kGameStatePlaying;

Then the AdWhirl methods

- (void)adWhirlWillPresentFullScreenModal {
if (self.state == kGameStatePlaying) {
[[CCDirector sharedDirector] pause];} }

- (void)adWhirlDidDismissFullScreenModal {
if (self.state == kGameStatePaused)
    return;
else {
    self.state = kGameStatePlaying;
    [[CCDirector sharedDirector] resume]; }}

- (NSString *)adWhirlApplicationKey {
return @"myadWhirlKeyGoesHere"; }

- (UIViewController *)viewControllerForPresentingModalView {
return viewController;}

-(void)adjustAdSize {
[UIView beginAnimations:@"AdResize" context:nil];
[UIView setAnimationDuration:0.2];
CGSize adSize = [adWhirlView actualAdSize];
CGRect newFrame = adWhirlView.frame;
newFrame.size.height = adSize.height;
CGSize winSize = [CCDirector sharedDirector].winSize;
    newFrame.size.width = winSize.width;
newFrame.origin.x = (self.adWhirlView.bounds.size.width - adSize.width)/2;
    newFrame.origin.y = (winSize.height - adSize.height);
adWhirlView.frame = newFrame;
[UIView commitAnimations]; }

- (void)adWhirlDidReceiveAd:(AdWhirlView *)adWhirlVieww {
[adWhirlView rotateToOrientation:UIInterfaceOrientationLandscapeRight];
[self adjustAdSize];
NSLog(@"Library - adWhirlDidReceiveAd");
NSLog(@"%@",[adWhirlView mostRecentNetworkName]); }

-(void)adWhirlDidFailToReceiveAd:(AdWhirlView *)adWhirlVieww usingBackup:(BOOL)yesOrNo {
NSLog(@"Library - adWhirlDidFailToReceiveAd");
NSLog(@"%@",[adWhirlView mostRecentNetworkName]); }

-(void)onEnter {

this is what the tutorial said and is wrong for version Cocos2d 2.0 users

//viewController = [(AppDelegate *)[[UIApplication sharedApplication] delegate] viewController];

this is the correct way

viewController = [(AppDelegate *)[[UIApplication sharedApplication] delegate] navController];

self.adWhirlView = [AdWhirlView requestAdWhirlViewWithDelegate:self];
self.adWhirlView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
[adWhirlView updateAdWhirlConfig];
CGSize adSize = [adWhirlView actualAdSize];
CGSize winSize = [CCDirector sharedDirector].winSize;
self.adWhirlView.frame = CGRectMake((winSize.width/2)-(adSize.width/2),winSize.height-adSize.height,winSize.width,adSize.height);
self.adWhirlView.clipsToBounds = YES;
[viewController.view addSubview:adWhirlView];
[viewController.view bringSubviewToFront:adWhirlView];
[super onEnter]; }

-(void)onExit {
if (adWhirlView) {
    [adWhirlView removeFromSuperview];
    [adWhirlView replaceBannerViewWith:nil];
    [adWhirlView ignoreNewAdRequests];
    [adWhirlView setDelegate:nil];
    self.adWhirlView = nil;
}
[super onExit]; }

- (void) dealloc {
self.adWhirlView.delegate = nil;
self.adWhirlView = nil; }

In My AppDelegate.h

Wrong:

//RootViewController *viewController; 
//UIViewController *viewController;

this is right and is provided in the 2.0 Cocos2d template so doesn't need to be added, just needs to be used:

UINavigationController *navController_;

And so these are not needed

//@property (nonatomic, retain) RootViewController *viewController;
//@property (nonatomic, retain) UIViewController *viewController;

AppDelegate.mm

@synthesize window=window_, navController=navController_, director=director_; 

not needed because we will be using the navController instead:

//viewController = viewController_;

DidFinishLaunchingWithOptions (with all references to viewController commented out)

//viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil];
//viewController.wantsFullScreenLayout = YES;
CCGLView *glView = [CCGLView viewWithFrame:[window_ bounds]
    pixelFormat:kEAGLColorFormatRGB565
            depthFormat:0
            preserveBackbuffer:NO
            sharegroup:nil   
            multiSampling:NO 
            numberOfSamples:0];
director_ = (CCDirectorIOS*) [CCDirector sharedDirector];
director_.wantsFullScreenLayout = YES;
[director_ setDisplayStats:NO];
[director_ setAnimationInterval:1.0/60];
[director_ setDelegate:self];
[director_ setProjection:kCCDirectorProjection2D];
[director_ setView:glView];
if( ! [director_ enableRetinaDisplay:YES] )CCLOG(@"Retina Display Not supported");
navController_ = [[UINavigationController alloc] initWithRootViewController:director_];
navController_.navigationBarHidden = YES;

this is the important line, setting the navController

[window_ addSubview:navController_.view];
[glView setMultipleTouchEnabled:YES];
//[viewController_ setView:glView];
//[window_ addSubview:viewController_.view];
[window_ makeKeyAndVisible];
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
[CCFileUtils setiPadSuffix:@"-ipad"];
[CCFileUtils setRetinaDisplaySuffix:@"-hd"];
[CCTexture2D PVRImagesHavePremultipliedAlpha:YES];
[director_ pushScene: [TitleScene scene]]; 
return YES;
Jim Rota
  • 1,781
  • 2
  • 16
  • 21
  • Are you setting the `viewController` property somewhere? If not, that would be one issue. – spring Jun 01 '12 at 17:24
  • Not sure what you mean by setting it. The code above is everything related to adWhirl (and view controller) in the CCLayer. Does it need to be set something like self.view = view controller in init? – Jim Rota Jun 03 '12 at 14:49

2 Answers2

0

You specify the viewController with this line:

viewController = [(AppDelegate *)[[UIApplication sharedApplication] delegate] viewController];

Are you sure that your appDelegate is setting its viewController property? In other words, is viewController nil? I would check that.

spring
  • 18,009
  • 15
  • 80
  • 160
  • I added: if (viewController == nil) {NSLog(@"viewController is nil");} and it does log that message. Looking at my AppDelegate, it appears I was trying to set viewController to a RootViewController, then switched it to a UIViewController in my effort to get AdWhirl working...neither one seems to work properly. Perhaps you can point me in the right direction for setting the viewController property... – Jim Rota Jun 04 '12 at 14:03
  • Post the method where you are doing that (edit your original question so the code formats properly). Also, how/when is your method `onEnter` getting called? – spring Jun 04 '12 at 15:32
  • I've added my AppDelegate code. I wasn't calling onEnter explicitly. I had assumed that it was automatically called when the scene launches... – Jim Rota Jun 04 '12 at 20:54
  • Ok - `onEnter` is not an appDelegate or `UIViewController` event so it will never get called (VC lifecycle events concern state of loading (into memory) and appearing (i.e. being displayed): `viewDidLoad`, `viewWillAppear`, `viewDidUnload` etc.). You should call it when the app finishes. Oh wait - this is Cocoa2? Ah - then perhaps that is an event in that API - but pertains to VCs only (not appDelegates)? Something to check. – spring Jun 04 '12 at 21:28
  • According to Cocos2d CCNode class reference, onEnter is called when you first enter a scene (i.e. when the transition starts), and onExit is called when you exit a scene (i.e. when the transition ends). So I'm thinking it has more to do with setting up a proper viewController (i.e., should it be a UIViewController or RootViewController, what is the difference?, did I miss a step or have something out of order in AppDelegate setup)... – Jim Rota Jun 05 '12 at 14:50
  • Found the problem. It's because Cocos2d version 2.0 uses a navController instead of RootViewController to handle things like ads and leader boards, etc. So the onEnter needs to have the following replace the first line: AppController *app = (AppController*) [[UIApplication sharedApplication] delegate]; UINavigationController *viewController = [app navController]; I will update the code above. Note: this AdWhirl implementation was from Ray Wenderlich tutorial, so it means most tutorials are out of date for version 2.0 users. – Jim Rota Jun 05 '12 at 15:11
  • Thanks for your encouragement along the way...it helped to motivate me and this one was tricky because it's a new version issue so there isn't any documentation or examples to follow. Now I know a whole lot more about View Controllers than before! – Jim Rota Jun 05 '12 at 22:16
0

If you still have this problem, use the code below.

Your previous is

[viewController.view addSubview:adWhirlView];<br>
[viewController.view bringSubviewToFront:adWhirlView];

My suggestion is

[[CCDirector sharedDirector].view addSubview:adWhirlView];<br>
[[CCDirector sharedDirector].view bringSubviewToFront:adWhirlView];

Maybe, after that can you see ads.

Nunser
  • 4,512
  • 8
  • 25
  • 37