i am trying to inset an iad banner at the bottom of my app but keep getting errors after following tutorials.
code as follows.
#interface DMKHomeViewController (UIViewcontroller ) <ADBannerViewDelegate>{
}
#end
#implementation DMKHomeViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)bannerViewDidLoadAd:(ADBannerView *)banner {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[banner setAlpha:1];
[UIView commitAnimations];
}
- (void)bannerView:(ADBannerView *)
banner didFailToReceiveAdWithError:(NSError *)error
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[banner setAlpha:0];
[UIView commitAnimations];
}
i keep getting the following error
* Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named ADBannerView'
* First throw call stack:
Please make sure that you have added the "iAd.framework"...
To do this go to the "App. Target", "General" and scroll down until you see "Linked Frameworks and Libraries". Hit "+" and select the iAd framework. See screen captures below...
You have not created object of AdBannerview..
First, create object for banner view and set delegate for it.
-(void)ViewDidLoad
{
[self createBannerView];
}
- (void)createBannerView {
Class cls = NSClassFromString(#"ADBannerView");
if (cls) {
ADBannerView *adView = [[cls alloc] initWithFrame:CGRectZero];
// Set the current size based on device orientation
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifier320x50;
adView.delegate = self;
adView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleRightMargin;
// Set initial frame to be offscreen
CGRect bannerFrame =adView.frame;
bannerFrame.origin.y = self.view.frame.size.height;
adView.frame = bannerFrame;
self.bannerView = adView;
[self.view addSubview:adView];
[adView release];
}
}
Related
I saw a few other similar questions but could find any answers... I have a shared iAd banner. The problem is when I load it in a modally presented NavigationController with a TableViewController, when I dismiss the TableViewController the Ad Banner in the MainViewController loses the ad and I receive the following error:
ADBannerView: Unhandled error (no delegate or delegate does not implement didFailToReceiveAdWithError:): Error Domain=ADErrorDomain Code=7 "The operation couldn’t be completed. Ad was unloaded from this banner" UserInfo=0x5b60e283649 {ADInternalErrorCode=7, NSLocalizedFailureReason=Ad was unloaded from this banner, ADInternalErrorDomain=ADErrorDomain}
The View setup us like this:
MainViewController --> NavigationController --> TableViewController
At another point in the app I modally present a ViewController with shared ad and I don't experience this issue. (MainViewController --> ViewController)
Here is the code from the TableViewController:
.h
#import <UIKit/UIKit.h>
#import <iAd/iAd.h>
#import "AppDelegate.h"
#interface TableViewController : UITableViewController <ADBannerViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView *table;
#property (strong, nonatomic) ADBannerView *adView;
#end
.m
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
// Insert Ad Bar
AppDelegate *appdelegate = (AppDelegate *)[[UIApplication sharedApplication ]delegate];
_adView = [appdelegate adView];
_adView.delegate = self;
self.canDisplayBannerAds = true;
if (IPAD) {
[_adView setFrame:CGRectMake(0, self.view.frame.size.height - 65, 320, 65)];
}
else {
[_adView setFrame:CGRectMake(0, self.view.frame.size.height - 50, 320, 50)];
}
if (!_adView.bannerLoaded) {
[_adView setAlpha:0];
}
[self.view addSubview:_adView];
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[banner setAlpha:1];
[UIView commitAnimations];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[banner setAlpha:0];
[UIView commitAnimations];
}
Any tips would be appreciated.
Thanks
The problem was because I was using:
self.canDisplayBannerAds = true;
as well as:
if (IPAD) {
[_adView setFrame:CGRectMake(0, self.view.frame.size.height - 65, 320, 65)];
}
else {
[_adView setFrame:CGRectMake(0, self.view.frame.size.height - 50, 320, 50)];
}
if (!_adView.bannerLoaded) {
[_adView setAlpha:0];
}
[self.view addSubview:_adView];
and thus was created 2 instances of the ad bar.
I have correctly implemented a shared iAd banner in the appDelegate and in certain views(which are adbanner delegates) it appears correctly. How ever in the views where I dont show the banner (so they are not adbanner delegates) when the appdelegate fails to retrieve a Banner since there is no current delegate and no current didFailToRecieveAdWithError method the console shows an error saying that efectively there is no method to recieve the error. Do i need to make the appDelegate also the AdBannerDelegate and put those methods inside?
In appDelegate:
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
// Override point for customization after application launch.
_UIiAD = [[ADBannerView alloc]init];
return YES;
}
in ViewController where I want a Banner:
- (CrystalAppDelegate *)appDelegate
{
return (CrystalAppDelegate *)[[UIApplication sharedApplication]delegate];
}
- (void)viewWillAppear:(BOOL)animated
{
_UIiAD = [[self appDelegate] UIiAD];
_UIiAD.delegate = self;
[_UIiAD setFrame:CGRectMake(0, 518, 320, 50)];
[self.view addSubview:_UIiAD];
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
NSLog(#"Banner did Load");
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[_UIiAD setAlpha:1];
[UIView commitAnimations];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
NSLog(#"Banner did not Load");
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[_UIiAD setAlpha:0];
[UIView commitAnimations];
}
-(void)viewWillDisappear:(BOOL)animated
{
_UIiAD.delegate = nil;
_UIiAD = nil;
[_UIiAD removeFromSuperview];
}
Problem is when i am in a view that doesnt have a banner i dont have these methods so when the appDelegate doesnt retrieve a iAdBanner there is no method to revieve the error.
I have finished my first application. I put iAd banners on it. And active iAd from iTunnes Connect.
I learned to add iAd from this tutorial. http://www.youtube.com/watch?v=fP2ijcXbCz4
Do I need to add something else to my code? Will ads be shown automatically?
#interface TOCGMainViewController () <ADBannerViewDelegate>
#property (strong, nonatomic) IBOutlet ADBannerView *iAdBanner;
#end
#implementation TOCGMainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if ([[ UIScreen mainScreen ] bounds ].size.height == 568 ) {
nibNameOrNil = [NSString stringWithFormat:#"%#_568", nibNameOrNil ?: #"TOCGMainViewController"];
}
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
}
if ([ADBannerView instancesRespondToSelector:#selector(initWithAdType:)]) {
self.iAdBanner = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
} else {
self.iAdBanner = [[ADBannerView alloc] init];
}
return self;
}
...
...
...
#pragma mark - ADBannerViewDelegate
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
NSUserDefaults *saveApp = [NSUserDefaults standardUserDefaults];
bool saved = [saveApp boolForKey:k_Save];
if (!saved) {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[banner setAlpha:1];
[UIView commitAnimations];
} else {
banner.hidden = YES;
[banner removeFromSuperview];
banner = nil;
banner.delegate = nil;
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[banner setAlpha:0];
[UIView commitAnimations];
}
#end
To test your iAd code, you can simply run the app on the simulator or your device. If you set up everything correctly, you should see a demo banner that indicates this. This will be replaced with the actual ads when the app goes into the store.
In the code below, the subview (cloud) oscillates on the location given.
On tapping that subview while oscillation, it moves out of the bounds to the right side, then moves in from the left.
But the tap gesture is not working on the whole subview, it works only on the right-side end of the oscillating subView.
I want slide out and in of cloud to work, whenever the whole subview of cloud is tapped.
Below is code of .h and .m file respectively.
File : OscillatingCloudsViewController.h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface OscillatingCloudsViewController : UIViewController
{
IBOutlet UIView *movingCloud1;
UIImage *cldImg;
}
- (IBAction)animateCloud;
- (IBAction)animateCloudBegin;
#end
File : OscillatingCloudsViewController.m
#import "OscillatingCloudsViewController.h"
#implementation OscillatingCloudsViewController
- (void) viewWillAppear:(BOOL)animated
{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureAnimateCloud)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
tapGesture.cancelsTouchesInView = YES;
[movingCloud1 addGestureRecognizer:tapGesture];
movingCloud1.userInteractionEnabled = YES;
[super viewWillAppear:
animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self animateCloud];
}
- (IBAction) animateCloud
{
cldImg = [UIImage imageNamed:#"cloud1.png"];
movingCloud1=[[UIView alloc]initWithFrame:CGRectMake(50, 50, cldImg.size.width, cldImg.size.height)];
[movingCloud1 setBackgroundColor:[UIColor colorWithPatternImage:cldImg]];
[self.view addSubview:movingCloud1];
movingCloud1.userInteractionEnabled = YES;
[self viewWillAppear:YES];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:5];
[UIView setAnimationRepeatCount:HUGE_VALF];
[UIView setAnimationRepeatAutoreverses:YES];
CGPoint pos = movingCloud1.center;
pos.x = 220.0f;
movingCloud1.center = pos;
[UIView commitAnimations];
}
- (void) animateCloudHidden
{
[movingCloud1 setHidden:YES];
}
- (IBAction)animateCloudBegin
{
movingCloud1.frame = CGRectMake(-100, 50, cldImg.size.width, cldImg.size.height);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:NO];
CGPoint pos = movingCloud1.center;
pos.x = cldImg.size.width;
movingCloud1.center = pos;
[UIView commitAnimations];
}
- (IBAction) tapGestureAnimateCloud
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:NO];
movingCloud1.center = CGPointMake(1100.0f, 81.5f);
[UIView commitAnimations];
[self performSelector:#selector(animateCloudBegin) withObject:nil afterDelay:2.0f];
[self performSelector:#selector(animateCloudHidden) withObject:nil afterDelay:3.0f];
[self performSelector:#selector(animateCloud) withObject:nil afterDelay:3.0f];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
I have understood your problem. In viewwillApper you are assing the Gesture and in inside animateCloud method your allocating your movingCloud1 UIView.
For implementing this you need to fallow the bello steps.
In ViewdidLoad you need to allocate and add the movingCloud1 view to you self.view.
After add the Gesture to movingCloud1 view.
Your tapGesture will work now. So inside your tapgesture method just you need to set the animation for your movingCloud1 view
I've been trying to figure out how to hide and show iAds in my Spritekit Scenes. Currently I have it setup like this:
ViewController.h
#import <UIKit/UIKit.h>
#import <SpriteKit/SpriteKit.h>
#import <iAd/iAD.h>
#interface ViewController : UIViewController <ADBannerViewDelegate> {
ADBannerView *adView;
}
-(void)showsBanner;
-(void)hidesBanner;
#end
ViewController.m
#import "ViewController.h"
#import <UIKit/UIKit.h>
#import <iAd/iAD.h>
#import "MyScene.h"
#import <SpriteKit/SpriteKit.h>
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the view.
SKView * skView = (SKView *)self.view;
skView.showsFPS = NO;
skView.showsNodeCount = NO;
// Create and configure the scene.
SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:scene];
self.canDisplayBannerAds = YES;
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.frame = CGRectOffset(adView.frame, 0, 0.0f);
adView.delegate=self;
[self.view addSubview:adView];
self.bannerIsVisible=NO;
}
-(void)bannerViewDidLoadAd:(ADBannerView *)banner {
if (!self.bannerIsVisible) {
[UIView beginAnimations:#"animatedAdBannerOn" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0.0, 0.0);
[UIView commitAnimations];
self.bannerIsVisible = YES;
}}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
if (!self.bannerIsVisible) {
[UIView beginAnimations:#"animatedAdBannerOff" context:NULL];
banner.frame = CGRectOffset(banner.frame, 0.0, 0.0);
[adView setAlpha:0];
[UIView commitAnimations];
self.bannerIsVisible = NO;
}
}
-(void)hidesBanner {
NSLog(#"HIDING BANNER");
[adView setAlpha:0];
self.bannerIsVisible = NO;
}
-(void)showsBanner {
NSLog(#"SHOWING BANNER");
[adView setAlpha:1];
self.bannerIsVisible = YES;
}
etc...
#end
Then in my scene I grab my viewcontroller with a pointer:
ViewController *controller;
controller = [[ViewController alloc] init];
[controller hidesBanner];
My nslog runs in the console so I know it's going through. But the banner won't hide. Any thoughts? I'm pretty new with objective c so I have a feeling I'm just doing something dumb.
Like Huygamer said, you're creating a new instance of a view controller so when you call your method [controller hidesBanner]; you're referring to another object.
The best approach here is to use NSNotificationCenter: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html
And send a message to your viewcontroller whenever you want to hide or show your ad:
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
//Add view controller as observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleNotification:) name:#"hideAd" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleNotification:) name:#"showAd" object:nil];
// Configure the view.
SKView * skView = (SKView *)self.view;
skView.showsFPS = NO;
skView.showsNodeCount = NO;
// Create and configure the scene.
SKScene * scene = [MyScene sceneWithSize:skView.bounds.size];
scene.scaleMode = SKSceneScaleModeAspectFill;
// Present the scene.
[skView presentScene:scene];
self.canDisplayBannerAds = YES;
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.frame = CGRectOffset(adView.frame, 0, 0.0f);
adView.delegate=self;
[self.view addSubview:adView];
self.bannerIsVisible=NO;
}
//Handle Notification
- (void)handleNotification:(NSNotification *)notification
{
if ([notification.name isEqualToString:#"hideAd"]) {
[self hidesBanner];
}else if ([notification.name isEqualToString:#"showAd"]) {
[self showBanner];
}
}
And in your scene:
[[NSNotificationCenter defaultCenter] postNotificationName:#"showAd" object:nil]; //Sends message to viewcontroller to show ad.
[[NSNotificationCenter defaultCenter] postNotificationName:#"hideAd" object:nil]; //Sends message to viewcontroller to hide ad.
Of course, there are 2 object and why you think it can do?
If you want to access the parent of skscene just do this
UIViewController *vc = self.view.window.rootViewController;
You can access the parent of this skscene and you can do hideBanner at the parent of this scene. Simple?
Here is what I did to make it work with SpriteKit Scenes (Xcode 6.1 and iOS 8.1 on iPhone 6):
Step 1- Add #import <"iAd/iAd.h"> in MyScene.h header file
Step 2- Make sure you declare your MyScene class to implement protocol in MyScene.h header file.
Step 3- Add the following code lines in your MyScene.m file inside -(Void)didMoveToView:(SKView *)view function.
ADBannerView* banner=[[ADBannerView alloc]initWithFrame:CGRectZero];
CGRect bannerFrame =CGRectMake(0, 667, self.view.frame.size.width, 0);
banner.frame=bannerFrame;
[self.view addSubview:banner];
banner.delegate=self;
Step 4- Implement the two methods of iAd
-(void)bannerViewDidLoadAd:(ADBannerView *)banner
{
CGRect bannerFrame =CGRectMake(0, 667-50, self.view.frame.size.width, 0);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
banner.frame=bannerFrame;
[UIView commitAnimations];
}
-(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
CGRect bannerFrame =CGRectMake(0, 667, self.view.frame.size.width, 0);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
banner.frame=bannerFrame;
[UIView commitAnimations];
}
The above code will move the Ad frame to scene when there is an Ad and will remove the frame if no Ad by animating the movement. Note that the last number in the frame rect is 0. It doesn't matter what you put there, the banner hight is fixed and doesn't change (50 pt).
Step 5- Respond to Ad actions by this code:
-(void)bannerViewActionDidFinish:(ADBannerView *)banner
{
[self startTimer];
}
-(BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
[gameTimer invalidate];
return YES;
}
This code will stop the game timer when a user clicks on the banner and resumes the game timer after the user returns back to the game. You can add your own code for saving and retrieving game data here.
Hope this helps.