Yesterday I was toying around with incorporating an iAd banner to my Cocos2D game. It was quite a struggle since the two didn’t play nicely together.
The first issue was that Cocos2D’s CCGLView – which is the director’s primary view – doesn’t support auto layout. Initially I used a scene to manage iAd’s ADBannerView – whenever an advertisement is ready then the scene will add the banner view as a subview of the director’s view and place some constraints to it. However the game crashed just after the constraints were added:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. CCGLView's implementation of -layoutSubviews needs to call super.'
Upon closer inspection, apparently [CCGLView layoutSubview] doesn’t call [UIView layoutSubview] and that what caused the crash. I could modify CCGLView to add this call and perhaps submit a patch to the Cocos2D team – but then it’ll take quite some time to get it incorporated to the main distribution, if the patch got approved at all (and that’s a big “if”).
Facing this then I tried adding the banner view to the director’s parent view. However this failed with a “ADBannerView must be part of a view hierarchy managed by a UIViewController”. Then I was stuck again.
Fortunately after googling around I found a way to send a message to the superclass’ superclass (i.e. the grandparent class) by making use of an Objective-C runtime function. Then it’s quite straightforward to make a subclass of CCGLView that supports autolayout:
//
// BSGLView.h
// AirKill
//
// Created by Sasmito Adibowo on 07-06-14.
// Basil Salad Software, http://basilsalad.com
//
// This code is in the public domain.
#import "CCGLView.h"
@interface BSGLView : CCGLView
@end
//
// BSGLView.m
// AirKill
//
// Created by Sasmito Adibowo on 07-06-14.
// Basil Salad Software, http://basilsalad.com
//
// This code is in the public domain.
//
#import <objc/message.h>
#import "BSGLView.h"
@implementation BSGLView
-(void)layoutSubviews
{
// We need this because CCGLView doesn't call UIView layoutSubviews and we need to add subviews
Class granny = [[self superclass] superclass];
struct objc_super theSuper = {self, granny};
objc_msgSendSuper(&theSuper,_cmd);
[super layoutSubviews];
}
@end
I then added used this class instead for CCDirector’s view and it now works nicely hosting a banner view on top of the game.
PS: you can use this gist instead to download the code above instead of taking the trouble to copy-paste it from this post.
That’s all for now. until next time!
0 thoughts on “Integrating iAd with Cocos2D”