Sprite Kit • Sprite Kit provides a graphics rendering and animation infrastructure that can be used to animate arbitrary textured images, or sprites. • Sprite Kit also provides other functionality that is useful for games, including basic sound playback support and physics simulation. • In addition, Xcode provides built-in support for Sprite Kit so that you can create complex special effects and texture atlases directly in Xcode. Sprite Kit • Create new SpriteKit Game project “Hello SpriteKit" Sprite Kit • By default, MyScene and Spaceship.png are added to the project - delete them.ViewController.h is simply : #import <UIKit/UIKit.h> #import <SpriteKit/SpriteKit.h> @interface ViewController : UIViewController @end SKView • Remove scene from viewDidLoad : - (void)viewDidLoad { [super viewDidLoad]; // Configure the view. SKView *skView = (SKView *)self.view; skView.showsFPS = YES; skView.showsNodeCount = YES; } SKScene • Sprite Kit content is placed in a window, just like other visual content. • • Sprite Kit content is rendered by the SKView class. • In order to create Hello scene, create a new class named HelloScene and make it a subclass of the SKScene class. The content that an SKView object renders is called a scene, which is an SKScene object. SKScene • • In ViewController.m import HelloScene header. In viewDidLoad method, create an instance of HelloScene and attach it to the view : // Get screen size CGRect screenRect = [[UIScreen mainScreen] bounds]; CGFloat screenWidth = screenRect.size.width; CGFloat screenHeight = screenRect.size.height; HelloScene* hello = [[HelloScene alloc] initWithSize:CGSizeMake(screenWidth, screenHeight)]; [skView presentScene: hello]; • Run. Sprite Kit SKScene • When designing a Sprite Kit–based game, you design different scene classes for each major chunk of your game interface. • • This first scene will display the traditional “Hello World” text. • First of all, in HelloScene.m we add a property contentCreated to track whether the scene has created a content or not : The code that draws the scene normally resides inside the didMoveToView: method, which is called whenever the scene is presented in a view. @interface HelloScene () @property BOOL contentCreated; @end didMoveToView method • Next we implement the scene’s didMoveToView: method. - (void)didMoveToView: (SKView *) view { if (!self.contentCreated) { [self createSceneContents]; self.contentCreated = YES; } } SKLabelNode • createSceneContents method sets the background colour, scale mode and attaches a new child - SKLabelNode: - (void)createSceneContents { self.backgroundColor = [SKColor blueColor]; self.scaleMode = SKSceneScaleModeAspectFit; [self addChild: [self newHelloNode]]; } text, font, position • Method newHelloNode creates and returns SKLabelNode: - (SKLabelNode *)newHelloNode { SKLabelNode *helloNode = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"]; helloNode.text = @"Hello, World!"; helloNode.fontSize = 42; helloNode.position = CGPointMake( CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)); return helloNode; } • Run. ( Hello Sprite Kit 1 ) Sprite Kit SKAction • Animations in SpriteKit are accomplished through actions ( SKAction - move, zoom, scale, pause etc. ) • Once the action ( or sequence of actions is defined ), it is called on specified node through runAction: method. • In order to access node(s) outside of method where they are defined ( e.g. newHelloNode ) we can give them names : helloNode.name = @"helloNode"; • The animation in this example starts when user touches the label. SKAction - (void)touchesBegan:(NSSet *) touches withEvent:(UIEvent *)event { SKNode *helloNode = [self childNodeWithName:@"helloNode"]; if (helloNode != nil) { helloNode.name = nil; SKAction *moveUp = [SKAction moveByX: 0 y: 100.0 duration: 0.5]; SKAction *zoom = [SKAction scaleTo: 2.0 duration: 0.25]; SKAction SKAction *pause = [SKAction waitForDuration: 0.5]; SKAction *fadeAway = [SKAction fadeOutWithDuration: 0.25]; SKAction *remove = [SKAction removeFromParent]; SKAction *moveSequence = [SKAction sequence:@[moveUp, zoom, pause, fadeAway, remove]]; [helloNode runAction: moveSequence]; } } Scene Transitions • Sprite Kit makes it easy to transition between scenes through the use of SKTransition • • Create new class SpaseshipScene, subclass of SKScene. Implementation is similar to HelloScene - we simply set the background to black. #import "SpaceshipScene.h" @interface SpaceshipScene () @property BOOL contentCreated; @end Scene Transitions @implementation SpaceshipScene - (void)didMoveToView:(SKView *)view { if (!self.contentCreated) { [self createSceneContents]; self.contentCreated = YES; } } - (void)createSceneContents { self.backgroundColor = [SKColor blackColor]; self.scaleMode = SKSceneScaleModeAspectFit; } @end Scene Transitions • In HelloScene implementation import “SpaceshipScene.h” and replace the call to runAction: with a new call : [helloNode runAction: moveSequence completion:^{ SKScene *spaceshipScene = [[SpaceshipScene alloc] initWithSize:self.size]; SKTransition *doors = [SKTransition doorsOpenVerticalWithDuration:0.5]; [self.view presentScene:spaceshipScene transition:doors]; }]; • Run. Complex Content • Complex content is normally built using many SKSpriteNode objects. • Our spaceship is going to be built using three nodes - hull and two lights. • In SpaceshipScene.m, add code to the createSceneContents method to create the spaceship : SKSpriteNode *spaceship = [self newSpaceship]; spaceship.position = CGPointMake( CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) - 150); [self addChild:spaceship]; Complex Content - (SKSpriteNode *)newSpaceship { SKSpriteNode *hull = [[SKSpriteNode alloc] initWithColor:[SKColor grayColor] size:CGSizeMake(64,32)]; SKAction *hover = [SKAction sequence:@[ [SKAction waitForDuration:1.0], [SKAction moveByX:100 y:50.0 duration:1.0], [SKAction waitForDuration:1.0], [SKAction moveByX:-100.0 y:-50 duration:1.0]]]; [hull runAction: [SKAction repeatActionForever:hover] ]; return hull; } Complex Content • Although we could add all three sprites directly to the scene, that isn’t the Sprite Kit way. • The blinking lights are part of the spaceship! If the spaceship moves, the lights should move with it. • The solution is to make the spaceship node their parent, in the same way that the scene is going to be the parent of the spaceship. • The coordinates of the lights are going to be specified relative to the parent node’s position, which is at the center of the sprite image. Complex Content • So, once the hull is created, we’ll couple of lights and set their parent to hull : SKSpriteNode *light1 = [self newLight]; light1.position = CGPointMake(-28.0, 6.0); [hull addChild:light1]; SKSpriteNode *light2 = [self newLight]; light2.position = CGPointMake(28.0, 6.0); [hull addChild:light2]; • We also need the newLight method : Complex Content - (SKSpriteNode *)newLight { SKSpriteNode *light = [[SKSpriteNode alloc] initWithColor:[SKColor yellowColor] size:CGSizeMake(8,8)]; SKAction *blink = [SKAction sequence:@[ [SKAction fadeOutWithDuration:0.25], [SKAction fadeInWithDuration:0.25]]]; SKAction *blinkForever = [SKAction repeatActionForever:blink]; [light runAction: blinkForever]; return light; } Complex Content • Run. ( Hello Sprite Kit 2 ) Physics • Sprite Kit provides a complete physics simulation which you can use to add automatic behaviours to nodes. • That is, instead of executing actions on the nodes, physics is automatically simulated on the node, causing it to move. • When it interacts with other nodes that are part of the physics system, collisions are automatically calculated and performed. • We add a physics body to the spaseship : hull.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:hull.size]; Physics • If you run it now, the spaceship plummets through the bottom of the screen. • In order to prevent the spaceship from being affected by physics interactions, set dynamic property to NO : hull.physicsBody.dynamic = NO; • Run it again and observe that spaceship is not affected by gravity anymore. Physics • Let’s create meteor shower and see how rocks interact with our spaceship. • In createSceneContents, after we added ship to the scene, we add makeRocks action which continuously spawns rocks : SKAction *makeRocks = [SKAction sequence: @[ [SKAction performSelector:@selector(addRock) onTarget:self], [SKAction waitForDuration:0.10 withRange:0.15] ]]; [self runAction: [SKAction repeatActionForever:makeRocks]]; Physics static inline CGFloat skRandf() { return rand() / (CGFloat) RAND_MAX; } static inline CGFloat skRand(CGFloat low, CGFloat high) { return skRandf() * (high - low) + low; } - (void)addRock { SKSpriteNode *rock = [[SKSpriteNode alloc] initWithColor:[SKColor brownColor] size:CGSizeMake(8,8)]; rock.position = CGPointMake( skRand(0, self.size.width), self.size.height-50); rock.name = @"rock"; rock.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:rock.size]; rock.physicsBody.usesPreciseCollisionDetection = YES; [self addChild:rock]; } Physics • Run. ( Hello Sprite Kit 3 ) The Archer Game Credit: iOS 7 App Essentials The Archer Game SKView Welcome Scene Welcome Label Node Archery Scene Archer Sprite Node Arrow Sprite Node Physics Body Ball Sprite Node Physics Body Game Over Label Node The Archer Game • Create new sprite kit based project “Archer”. In project setting, set orientation to portrait only. • Delete scene and default png from project and in ViewController delete scene reference : - (void)viewDidLoad { [super viewDidLoad]; // Configure the view. SKView * skView = (SKView *)self.view; skView.showsFPS = YES; skView.showsNodeCount = YES; } Welcome Scene • • Create new class WelcomeScene subclass of SKScene. As before, we add boolean property sceneCreated and implement didMoveToView method : @interface WelcomeScene () @property BOOL sceneCreated; @end Welcome Scene @implementation WelcomeScene - (void) didMoveToView:(SKView *)view { if (!self.sceneCreated) { self.backgroundColor = [SKColor greenColor]; self.scaleMode = SKSceneScaleModeAspectFill; [self addChild: [self createWelcomeNode]]; self.sceneCreated = YES; } } Welcome Scene - (SKLabelNode *) createWelcomeNode { SKLabelNode *welcomeNode = [SKLabelNode labelNodeWithFontNamed:@"Bradley Hand"]; welcomeNode.name = @"welcomeNode"; welcomeNode.text = @"Tap Screen to Play"; welcomeNode.fontSize = 24; welcomeNode.fontColor = [SKColor blackColor]; welcomeNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)); return welcomeNode; } Welcome Scene • In ViewController, viewDidLoad method, we create the welcome scene and attach it to the view: WelcomeScene *welcome = [[WelcomeScene alloc] initWithSize:CGSizeMake(skView.bounds.size.width, skView.bounds.size.height)]; [skView presentScene:welcome]; • Don’t forget to import “WelcomeScene.h” Welcome Scene • Run. Archery Scene • Similar, at this point, to welcome scene. Besides boolean property sceneCreated, we also declare score and ballCount properties: @interface ArcheryScene () @property BOOL sceneCreated; @property int score; @property int ballCount; @end Archery Scene @implementation ArcheryScene - (void)didMoveToView:(SKView *)view { if (!self.sceneCreated) { self.score = 0; self.ballCount = 40; [self initArcheryScene]; self.sceneCreated = YES; } } - (void) initArcheryScene { self.backgroundColor = [SKColor whiteColor]; self.scaleMode = SKSceneScaleModeAspectFill; } Transition • In order to make transition from welcome scene to archery scene we need to implement method touchesBegan:withEvent - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { SKNode *welcomeNode = [self childNodeWithName:@"welcomeNode"]; if (welcomeNode != nil) { SKAction *fadeAway = [SKAction fadeOutWithDuration:1.0]; Transition [welcomeNode runAction:fadeAway completion:^{ SKScene *archeryScene = [[ArcheryScene alloc] initWithSize:self.size]; SKTransition *doors = [SKTransition doorwayWithDuration:1.0]; [self.view presentScene:archeryScene transition:doors]; } ]; } } • • Don’t forget to import “ArcheryScene.h” in WelcomeScene.m. Run. ( Archer 1 ) Texture Atlas • Before textures can be used on a sprite node, the texture images first need to be added to the project. • Textures take the form of image files and may be added individually to the Supporting Files folder of the project. • For larger numbers of texture files, it is more efficient (both for the developer and the application) to create a texture atlas. • In the case of the archer sprite, this will require twelve image files to animate the loading and subsequent shooting of an arrow. • As such, a texture atlas will be used to store these animation frame images. Texture Atlas • To add the atlas to the project, drag and drop the archer.atlas folder into the Supporting Files folder in the Xcode project navigator panel: • Verify in Targets, Archer, Build Settings that Texture Atlas Generation is enabled : • When the archer sprite is first initialized it needs to be textured with the archer001.png file from the texture atlas. • This takes place in the createArcherNode method: Texture Atlas - (SKSpriteNode *)createArcherNode { SKSpriteNode *archerNode = [[SKSpriteNode alloc] initWithImageNamed:@"archer001.png"]; archerNode.name = @"archerNode"; return archerNode; } • Method is called in initArcheryScene SKSpriteNode *archerNode = [self createArcherNode]; archerNode.position = CGPointMake( CGRectGetMinX(self.frame)+55, CGRectGetMidY(self.frame)); [self addChild:archerNode]; Texture Atlas • Run. Animation Texture Atlas • In order to animate archer whenever user touches the screen, first of all we define the private property: @property NSArray *archerAnimation; • Array is then populated in initArcheryScene method: Animation Texture Atlas NSMutableArray *archerFrames = [NSMutableArray array]; SKTextureAtlas *archerAtlas = [SKTextureAtlas atlasNamed:@"archer"]; for (int i = 1; i <= archerAtlas.textureNames.count; i++) { NSString *texture = [NSString stringWithFormat:@"archer%03d", i]; [archerFrames addObject: [archerAtlas textureNamed:texture]]; } self.archerAnimation = archerFrames; Animation Texture Atlas • Now that an array of textures for the animation action has been created and initialized, code now needs to be written to perform the animation. • Since this animation is triggered by a touch on the screen, this code needs to go in the touchesBegan:withEvent method of the ArcheryScene class. Animation Texture Atlas - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { SKNode *archerNode = [self childNodeWithName:@"archerNode"]; if (archerNode != nil) { SKAction *animate = [SKAction animateWithTextures:self.archerAnimation timePerFrame: 0.05]; [archerNode runAction:animate]; } } • Run and observe that sprite is animated. Shoot! • In order for Archer to shoot arrows, first of all, we need an “ArrowTexture.png” in Supporting Files • Next we have to create the arrow node, position it to the right of the archer sprite node and assigns it the name arrowNode. • A physics body is then assigned to the node, using the size of the node itself as the boundary of the body and enabling precision collision detection. Shoot! - (SKSpriteNode *) createArrowNode { SKSpriteNode *arrow = [[SKSpriteNode alloc] initWithImageNamed:@"ArrowTexture.png"]; arrow.position = CGPointMake( CGRectGetMinX(self.frame)+100, CGRectGetMidY(self.frame)); arrow.name = @"arrowNode"; arrow.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:arrow.frame.size]; arrow.physicsBody.usesPreciseCollisionDetection = YES; return arrow; } Shoot! • In order to propel the arrow across the scene, a physical force needs to be applied to it. • The creation and propulsion of the arrow sprite needs to be timed to occur at the end of the archer animation sequence. • This can be achieved via some minor modifications (after the action animate) to the touchesBegan method: Shoot! SKAction *shootArrow = [SKAction runBlock:^{ SKNode *arrowNode = [self createArrowNode]; [self addChild:arrowNode]; [arrowNode.physicsBody applyImpulse:CGVectorMake(35.0, 0)]; }]; SKAction *sequence = [SKAction sequence:@[animate, shootArrow]]; [archerNode runAction:sequence]; • Run and shoot some arrows. Targets • • • The goal of the game is to shoot something (balls). Copy BallTexture.png into Supporting Files folder. Next we need the createBallNode method in our ArcheryScene.m : Targets - (void) createBallNode { SKSpriteNode *ball = [[SKSpriteNode alloc] initWithImageNamed:@"BallTexture.png"]; ball.position = CGPointMake( randomBetween(200, self.size.width), self.size.height-50); ball.name = @"ballNode"; ball.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:(ball.size.width/2)-7]; ball.physicsBody.usesPreciseCollisionDetection = YES; [self addChild:ball]; } Targets • createBallNode method uses random number generation used in calculating the X coordinate of the ball sprite node: static inline CGFloat randomFloat() { return rand() / (CGFloat) RAND_MAX; } static inline CGFloat randomBetween(CGFloat low, CGFloat high) { return randomFloat() * (high - low) + low; } Targets • Next, modify the initArcheryScene method to create an action to release a total of 40 balls at one second intervals: SKAction *releaseBalls = [SKAction sequence:@[[SKAction performSelector:@selector(createBallNode) onTarget:self], [SKAction waitForDuration:1] ]]; [self runAction: [SKAction repeatAction:releaseBalls count:self.ballCount]]; Targets • • Run. Bit too much gravity. Change it in didMoveToView method to : self.physicsWorld.gravity = CGVectorMake(0, -1.0); • Run again ( Archer 2 ) Collision Detection • When detecting collisions within a Sprite Kit scene, a delegate method is called each time a collision is detected. • This method will only be called, however, if the colliding nodes are configured appropriately using category bit masks. • We begin by editing the ArcheryScene.m file and adding two category bit masks at the top of the @implementation section: static const uint32_t arrowCategory = 0x1 << 0; static const uint32_t ballCategory = 0x1 << 1; Collision Detection • Having declared the masks, these need to be assigned to the respective node objects when they are created within the game ( createArrowNode and createBallNode ). • This is achieved by assigning the mask to the categoryBitMask property of the physics body assigned to the node. arrow.physicsBody.categoryBitMask = arrowCategory; ball.physicsBody.categoryBitMask = ballCategory; Collision vs Contact • When a contact occurs, two nodes are able to touch or even occupy the same space in a scene. • A collision involves contact between two nodes that cannot occupy the same space in the scene. • The type of contact for which notification is required is specified by assigning contact and collision bit masks to the physics body of one of the node categories involved in the contact. arrow.physicsBody.collisionBitMask = arrowCategory | ballCategory; arrow.physicsBody.contactTestBitMask = arrowCategory | ballCategory; Contact Delegate • When the Sprite Kit physics system detects a collision or contact, it needs a way to notify the application code that such an event has occurred. • It does this by calling methods on the class instance that has been registered as the contact delegate ( ArcheryScene.h ). #import <SpriteKit/SpriteKit.h> @interface ArcheryScene : SKScene <SKPhysicsContactDelegate> @end Contact Delegate • In didMoveToView method we have to set the delegate : self.physicsWorld.contactDelegate = self; • And implement didBeginContact in ArcheryScene.m : - (void) didBeginContact:(SKPhysicsContact *)contact { SKSpriteNode *firstNode, *secondNode; firstNode = (SKSpriteNode *)contact.bodyA.node; secondNode = (SKSpriteNode *) contact.bodyB.node; Contact Delegate if ((contact.bodyA.categoryBitMask == arrowCategory) && (contact.bodyB.categoryBitMask == ballCategory)) { CGPoint contactPoint = contact.contactPoint; float contact_y = contactPoint.y; float target_y = secondNode.position.y; float margin = secondNode.frame.size.height/2 - 25; if ((contact_y > (target_y - margin)) && (contact_y < (target_y + margin))) { NSLog(@"Hit"); self.score++; } } } Fixed Joint • • Run it and observe the output in the console. • Start by dragging ArrowHitTexture.png into the Supporting Files folder. • In order to “embed” the arrow into a ball, we need to create fixed joint between two nodes ( arrow and ball ). • Here we’ll need the x coordinate as well: To make thing more interesting, how would one embed arrow into a ball when we hit the ball? float contact_x = contactPoint.x; Fixed Joint if ((contact_y > (target_y - margin)) && (contact_y < (target_y + margin))) { SKPhysicsJointFixed *joint = [SKPhysicsJointFixed jointWithBodyA:contact.bodyA bodyB:contact.bodyB anchor:CGPointMake(contact_x, contact_y)]; [self.physicsWorld addJoint:joint]; SKTexture *texture = [SKTexture textureWithImageNamed:@"ArrowHitTexture"]; firstNode.texture = texture; self.score++; } Game Over • All that now remains is to display the score to the user when all of the balls have been released. • This will require a new label node and a small change to an action sequence followed by a transition to the welcome scene so the user can start a new game. • Begin by adding the method to create the label node in the ArcheryScene.m file: Game Over - (SKLabelNode *) createScoreNode { SKLabelNode *scoreNode = [SKLabelNode labelNodeWithFontNamed:@"Bradley Hand"]; scoreNode.name = @"scoreNode"; NSString *newScore = [NSString stringWithFormat:@"Score: %i", self.score]; scoreNode.text = newScore; scoreNode.fontSize = 60; scoreNode.fontColor = [SKColor redColor]; scoreNode.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)); return scoreNode; } Game Over • Next, implement the gameOver method which will display the score label node and then transition back to the welcome scene ( remember to import “WelcomeScene.h” ): - (void) gameOver { SKLabelNode *scoreNode = [self createScoreNode]; [self addChild:scoreNode]; SKAction *fadeOut = [SKAction sequence: @[[SKAction waitForDuration:3.0], [SKAction fadeOutWithDuration:3.0] ]]; Game Over SKAction *welcomeReturn = [SKAction runBlock:^{ SKTransition *transition = [SKTransition revealWithDirection:SKTransitionDirectionDown duration:1.0]; WelcomeScene *welcomeScene = [[WelcomeScene alloc] initWithSize:self.size]; [self.scene.view presentScene: welcomeScene transition:transition]; }]; SKAction *sequence = [SKAction sequence:@[fadeOut, welcomeReturn]]; [self runAction:sequence]; } Game Over • Finally, add a completion handler that calls the gameOver method to the ball release action in the initArcheryScene method: [self runAction:[SKAction repeatAction:releaseBalls count:self.ballCount] completion:^{ [self gameOver]; } ]; Game Over • Run again ( Archer 3 ) Particle Emitter • The Sprite Kit particle emitter is essentially a mechanism designed to add special effects to games. • It comprises the SKEmitterNode class and the Particle Emitter Editor bundled with Xcode. • Create new file, iOS, Resource, SpriteKit Particle File. Particle Emitter Particle Emitter • Select spark effect and save files as BurstParticle.sks Particle Emitter • In method didBeginContact, we don’t need anymore contact_x, neither the code that embeds arrow into the ball, but we’ll need target_x: float target_x = secondNode.position.x; float target_y = secondNode.position.y; float margin = secondNode.frame.size.height/2 - 25; if ((contact_y > (target_y - margin)) && (contact_y < (target_y + margin))) { self.score++; } Particle Emitter • Create SKEmitterNode from the archive in the BurstParticle file, remove the ball node from the scene and replace it at the same position with the emitter: NSString *burstPath = [[NSBundle mainBundle] pathForResource:@“BurstParticle" ofType:@"sks"]; SKEmitterNode *burstNode = [NSKeyedUnarchiver unarchiveObjectWithFile:burstPath]; burstNode.position = CGPointMake(target_x, target_y); [secondNode removeFromParent]; [self addChild:burstNode]; Particle Emitter • If you run it at this point, well, it does not look very good. Select BurstParticle.sks and SKNode Inspector • • Change background to white. • Set position range to 86 ( size of the ball ) Set particles birthrate to 15 and maximum to 8. Particle Emitter • Set the color ramp to white and Blend Mode to Alpha • • Drag BallFragment.png into Support Files Folder. Change Particle Texture Sound Effects • If you want to add a sound effect, copy ballburst.mp3 into Support Files Folder. • In didBeginContact method, before we replace ball with the particle emitter, play that sound: [self runAction: [SKAction playSoundFileNamed:@"ballburst.mp3" waitForCompletion:NO] ]; • Run. ( Archer 4 ) iAd Framework • How to make some money out of your app? 1. Get paid by the third party to develop app. 2. Sell app in the app store. 3. Make it free and create in-app purchases. 4. Make it free and make some money from the advertisement. • In order to display advertisements, we need to add iAd Framework iAd Framework • • Create new project, “iAdDemo”, single view application. • Add few labels and Ad BannerView from the Object Library. Select project, targets, iAdDemo, General and add iAd.framework: iAd Framework • Your Main.storyboard should resemble: iAd Framework • Using Assistant Editor, create an outlet for the banner: #import <UIKit/UIKit.h> #import <iAd/iAd.h> @interface ViewController : UIViewController <ADBannerViewDelegate> @property (weak, nonatomic) IBOutlet ADBannerView *adBanner; @end iAd Framework • The iAd framework provides several delegate methods for managing ads. • These allow us to know: 1. when an ad is about to be shown or it has already been shown 2. when a failure occurs and no more ads can be served 3. when the user taps on an ad to view it on full-screen mode iAd Framework • In viewDidLoad method we set banner’s delegate to itself and initially hide the banner: self.adBanner.delegate = self; self.adBanner.alpha = 0.0; • The delegate methods are: -(void)bannerViewWillLoadAd:(ADBannerView *)banner { NSLog(@"Ad Banner will load ad."); } Called when a new advertisement is about to be loaded. Note that when this method is called the ad is not yet ready to be displayed. iAd Framework -(void)bannerViewDidLoadAd:(ADBannerView *)banner{ NSLog(@"Ad Banner did load ad."); // Show the ad banner. [UIView animateWithDuration:0.5 animations:^{ self.adBanner.alpha = 1.0; }]; } Called after a new ad has been loaded and is ready to be displayed. Here we make the banner visible. iAd Framework -(BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave { NSLog(@"Ad Banner action is about to begin."); return YES; } Called when the user taps on the banner, and the ad is going to be displayed in a full size modal view. iAd Framework -(void)bannerViewActionDidFinish:(ADBannerView *)banner { NSLog(@"Ad Banner action did finish"); } Called when the full-screen view with the add gets dismissed. iAd Framework -(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error { NSLog(@"Unable to show ads. Error: %@", [error localizedDescription]); // Hide the ad banner. [UIView animateWithDuration:0.5 animations:^{ self.adBanner.alpha = 0.0; }]; } Called when no ads are available to be delivered to the app. Here we hide the banner. • Run. ( iAdDemo ) iAd Framework Die Ende
© Copyright 2024