iAd tutorial for iOS: How To Integrate iAd into Your iPhone App

An iAd tutorial on how to add Apple’s iAds into your iPhone app – to make some extra money! By Ray Wenderlich.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 3 of this article. Click here to view the first page.

Simple iAd Integration

Ok, now let’s get to the fun part – integrating iAd!

First, make the following changes to PortMeGameDetailsController:

// In the import section
#import "iAd/ADBannerView.h"

// Modify the PortMeGameDetailsController interface
@interface PortMeGameDetailsController : UIViewController 
    <GameSelectionDelegate, UISplitViewControllerDelegate, ADBannerViewDelegate> {

// Inside the PortMeGameDetailsController interface
UIView *_contentView;
id _adBannerView;
BOOL _adBannerViewIsVisible;

// After the interface
@property (nonatomic, retain) IBOutlet UIView *contentView;
@property (nonatomic, retain) id adBannerView;
@property (nonatomic) BOOL adBannerViewIsVisible;

We first include the iAd headers and mark the view controller as implementing the ADBannerViewDelegate. This way, we can receive events as ads become available or not.

We then declare a property to keep track of the content view that contains all of the controls (basically the inner UIView). We also declare a variable to keep track of our iAd banner view, and whether or not it’s currently visible.

Note that we declare the iAd banner view as an id variable rather than as a ADBannerView. This is because we want to ensure backwards compatibility all the way to OS 3.0, and the ADBannerView class is only available on 4.0+, so we need to weak link against it.

Before we forget, let’s hook up our content view to the new outlet we just made. Make sure you save PortMeGameDetailsController.h, go back to PortMeGameDetailsController.xib, control-drag from the File’s Owner to the inner (second) UIView, and connect it to the contentView outlet.

Then switch over to PortMeGameDetailsController.m and make the following changes:

// In the synthesize section
@synthesize contentView = _contentView;
@synthesize adBannerView = _adBannerView;
@synthesize adBannerViewIsVisible = _adBannerViewIsVisible;

// In the dealloc section
self.contentView = nil;
self.adBannerView = nil;

Next, we’re going to add the meat of the code. But there’s a lot of it – so let’s break it down into 6 steps.

1) Add helper functions to get height of iAd banner

- (int)getBannerHeight:(UIDeviceOrientation)orientation {
    if (UIInterfaceOrientationIsLandscape(orientation)) {
        return 32;
    } else {
        return 50;
    }
}

- (int)getBannerHeight {
    return [self getBannerHeight:[UIDevice currentDevice].orientation];
}

There are several places in the rest of the code where we’re going to want to know how large the banner view should be given a particular orientation. Currently iAds have two possible sizes: 320×50 for portrait, or 480×32 for landscape. So we simply retrieve the proper height based on the passed in orientation.

2) Add helper function to create the iAd view

- (void)createAdBannerView {
    Class classAdBannerView = NSClassFromString(@"ADBannerView");
    if (classAdBannerView != nil) {
        self.adBannerView = [[[classAdBannerView alloc] 
            initWithFrame:CGRectZero] autorelease];
        [_adBannerView setRequiredContentSizeIdentifiers:[NSSet setWithObjects: 
            ADBannerContentSizeIdentifier320x50, 
            ADBannerContentSizeIdentifier480x32, nil]];
        if (UIInterfaceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
            [_adBannerView setCurrentContentSizeIdentifier:
                ADBannerContentSizeIdentifier480x32];
        } else {
            [_adBannerView setCurrentContentSizeIdentifier:
                ADBannerContentSizeIdentifier320x50];            
        }
        [_adBannerView setFrame:CGRectOffset([_adBannerView frame], 0, 
                -[self getBannerHeight])];
        [_adBannerView setDelegate:self];
        
        [self.view addSubview:_adBannerView];        
    }
}

This helper function creates an ADBannerView in a manner that is safe to use across multiple OS versions. It uses weak linking and NSClassFromString to check if the ADBannerView class is available – if it is not, the method will return nil and the function will bail.

However, if it is available it creates an instance of the class. It then uses the setRequiredContentSizeIdentifiers to specify what kind of ads this app needs. For our case, our app supports both portrait and landscape modes so it needs both ad options.

It then calls setCurrentContentSizeIdentifier to tell iAd which ad it should display. We simply choose the correct one by looking at the current orientation.

Next, we need to set the frame for the iAd. Note there’s some funky business here – we actually set the frame of the view to be offscreen! This is because we don’t know if an ad is available yet, and we don’t want to display the view until we know one is.

We set our view controller as the delegate so that we can receive notice about iAds being available or not. Then finally we ad the new iAd banner view as a subview of our view!

Note something subtle about the above – we always use message passing syntax rather than dot notation (i.e. [_adBannerView setRequiredContentSizeIdentifiers:…] instead of _adBannerView.requiredContentSizeIdentifiers = …). This is again to make sure everything runs fine on OS 3.0+.

3) Add function to size views correctly

- (void)fixupAdView:(UIInterfaceOrientation)toInterfaceOrientation {
    if (_adBannerView != nil) {        
        if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
            [_adBannerView setCurrentContentSizeIdentifier:
                ADBannerContentSizeIdentifier480x32];
        } else {
            [_adBannerView setCurrentContentSizeIdentifier:
                ADBannerContentSizeIdentifier320x50];
        }          
        [UIView beginAnimations:@"fixupViews" context:nil];
        if (_adBannerViewIsVisible) {
            CGRect adBannerViewFrame = [_adBannerView frame];
            adBannerViewFrame.origin.x = 0;
            adBannerViewFrame.origin.y = 0;
            [_adBannerView setFrame:adBannerViewFrame];
            CGRect contentViewFrame = _contentView.frame;
            contentViewFrame.origin.y = 
                [self getBannerHeight:toInterfaceOrientation];
            contentViewFrame.size.height = self.view.frame.size.height - 
                [self getBannerHeight:toInterfaceOrientation];
            _contentView.frame = contentViewFrame;
        } else {
            CGRect adBannerViewFrame = [_adBannerView frame];
            adBannerViewFrame.origin.x = 0;
            adBannerViewFrame.origin.y = 
                -[self getBannerHeight:toInterfaceOrientation];
            [_adBannerView setFrame:adBannerViewFrame];
            CGRect contentViewFrame = _contentView.frame;
            contentViewFrame.origin.y = 0;
            contentViewFrame.size.height = self.view.frame.size.height;
            _contentView.frame = contentViewFrame;            
        }
        [UIView commitAnimations];
    }   
}

This is a helper function we can call to make sure our views are in the right position. If ads are available, we want the ad banner view to be at the top of the screen and the content view shrunk a bit to fill the rest of the area. If ads are not available, we want the ad banner view offscreen and the content view as large as the entire view here.

And that’s exactly what the above function does. It looks long, but is fairly simple and self-explanatory. Note that we wrap the resizing code in an animation block to make things look awesome.

4) Call createAdView in viewDidLoad

- (void)viewDidLoad {
    [self createAdBannerView];
}

We want to create our ad view as soon as our view is loaded, even if we aren’t ready to display it quite yet.

5) Call fixupAdView in viewWillAppear and willRotateToInterfaceOrientation

- (void) viewWillAppear:(BOOL)animated {
    [self refresh];
    [self fixupAdView:[UIDevice currentDevice].orientation];
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [self fixupAdView:toInterfaceOrientation];
}

We need to fix up our ad view in viewWillAppear, because the device may have changed orientations in the time between when our view was visible last and now. And we obviously need to change it upon rotation as well!

6) Implement ADBannerViewDelegate

#pragma mark ADBannerViewDelegate

- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
    if (!_adBannerViewIsVisible) {                
        _adBannerViewIsVisible = YES;
        [self fixupAdView:[UIDevice currentDevice].orientation];
    }
}

- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
    if (_adBannerViewIsVisible)
    {        
        _adBannerViewIsVisible = NO;
        [self fixupAdView:[UIDevice currentDevice].orientation];
    }
}

Now that we have our helper functions, implementing the ADBannerViewDelegate methods are quite simple. We simply toggle whether the ad banner view should be visible or not, and call fixupAdView.

Done!

And that’s it! Compile and run your project, and you should see ads appear correctly in both portrait and landscape mode.

iAd in List View - Portrait Mode

iAd in List View - Landscape Mode

And best yet – if you run the code on an iPad or iPhone 3.0 device it will work just fine as well, but without ads!