how to implement AdBannerview and ADBannerview delegate - iphone

I am having trouble implementing ADBannerView and its delegate protocol.
I implemented the following code in my view class (also made the view conform to the ADBannerViewDelegate protocol):
//add iAds
ADBannerView *adView = [[ADBannerView alloc] initWithFrame: CGRectMake(0, 318, 320, 50)];
adView.requiredContentSizeIdentifiers = [NSSet setWithObjects: ADBannerContentSizeIdentifierPortrait, ADBannerContentSizeIdentifierLandscape, nil];
adView.delegate = self;
//adView.delegate = ADBannerViewDelegate;
[self.view addSubview: adView];
then I created a class for the ADBannerViewDelegate, with the following .m
//
// ADBannerViewDelegate.m
//
#import "ADBannerViewDelegate.h"
#implementation ADBannerViewDelegate
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
NSLog(#"bannerview did not receive any banner due to %#", error);}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner{NSLog(#"bannerview was selected");}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave{return willLeave;}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {NSLog(#"banner was loaded");}
#end
the banners are eventually presented but the console keep throwing the following type of errors:
2011-02-27 15:00:54.108 app[31639:207] ADBannerView: Unhandled error (no delegate or delegate does not implement didFailToReceiveAdWithError:): Error Domain=ADErrorDomain Code=5 "The operation couldn’t be completed. Banner view is visible but does not have content" UserInfo=0x6356a40 {ADInternalErrorCode=5, NSLocalizedFailureReason=Banner view is visible but does not have content}
and the delegate functions are not doing anything , so no NSLog at all. Obviously not catching the errors.
I am stumped. I guess I am missing something in the linkage of the Adbanner view calls in the view and the delegate. Not sure how to do it or what is wrong.
Any help? Thanks in advance.
Jason

The reason why is you told the AdBannerView that you are its delegate but you never put it in your implementation file. Your implementation file should look like this (notice the line with #implmentation):
//
// ADBannerViewDelegate.m
//
#import "ADBannerViewDelegate.h"
#implementation ADBannerViewDelegate<ADBannerViewDelegate>
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
NSLog(#"bannerview did not receive any banner due to %#", error);}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner{NSLog(#"bannerview was selected");}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave{return willLeave;}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {NSLog(#"banner was loaded");}
#end
And also you shouldn't name your class ADBannerViewDelegate. Your class should be a delegate (respond to it) to ADBannerView but not be named after it.

i successfully integrated iAds in my app using this tutorial:
http://www.raywenderlich.com/1371/how-to-integrate-iad-into-your-iphone-app
might help you too.

You don't try to implement a class named ADBannerViewDelegate, you put those methods in the implementation for your view class.
(If you actually named your view class "ADBannerViewDelegate", don't. It's confusing.)

For me it was the target and the device, I ran it on the 4.3 simulator and my ipad 2 but the app was for iphone 5.1, when I changed the target all went swimmingly

you can Use this link its very helpful
http://codewithchris.com/iad-tutorial/

Related

iAd not showing banner ads

I am building an app in which I want to us iAd banners. the viewcontroller in which I want to show the ad is a UIViewController. I am using storyboards. I implemented the iAd banner exactly as apple shows/demonstrates here:
add iAd framework
import "<iAd/iAd.h>" header
inserted self.canDisplayBannerAds = YES;
but when I run my app, no iAd is showing up. do I forget something? Thank you so much in advance
I had a bit different issue, but the answer fits to your question as well. I updated my old xib file (was from XCode 5.1) to use Size Classes in XCode 6.0. After the update ads showed only in iPhone 4 - 5 and 5s. iPhone 6 and iPhone 6 Plus was without banners (simulators showed the same results as the external devices). When using xib file and using
self.canDisplayBannerAds = YES;
in my situation I moved this command from viewDidLoad to viewDidAppear and banner showed up. Now I can see banners in all devices.
In your .h :
#interface MyViewController : UIViewController <ADBannerViewDelegate>
Add a banner view in your xib file and link this banner view with an IBOutlet
#property (nonatomic, strong) IBOutlet ADBannerView *iAdBannerView;
add the following code to display your ad :
#pragma mark - ADBannerViewDelegate
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
NSLog(#"banner loaded");
// Display BannerView
_iAdBannerView.hidden = NO;
[UIView animateWithDuration:0.4f
animations:^{
_iAdBannerView.alpha = 1.0f;
}];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
// Print error
NSLog(#"error banner failed :\n%#", error);
// Hide BannerView
[UIView animateWithDuration:0.4f
animations:^{
_iAdBannerView.alpha = 0.0f;
} completion:^(BOOL finished) {
_iAdBannerView.hidden = YES;
}];
}
and normally your adbanner will appear when you receive and ad and disappear otherwise.
The problem was that I had to sign the iAd contract in itunes connect, which I had not done yet. it works fine now!

iAd doesn't hide when it fails to load?

This seems like the dumbest question ever, but after wading through all of Apple's documentation and the useless online tutorials, I still can't figure out how to properly implement iAds into my application. So, my app starts off in a table view controller, and I have an iAd object underneath the navigation bar and above the table.
Now, in my code: (I also have the iAd framework added)
#import <UIKit/UIKit.h>
#import <iAd/iAd.h>
#interface MasterTableViewController : UITableViewController <ADBannerViewDelegate>
{
IBOutlet ADBannerView *iAd;
}
#property(nonatomic, readonly, getter=isBannerLoaded) BOOL bannerLoaded;
#end
then in the .m file
#import "MasterTableViewController.h"
#interface MasterTableViewController ()
#end
#implementation MasterTableViewController
#synthesize bannerLoaded;
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
if (!willLeave)
{
// nothing in this case thanks to ARC
}
return YES;
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
iAd.hidden = NO;
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
iAd.hidden = YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
for (int i = 0; i > 0; i++)
{
if (bannerLoaded)
{
iAd.hidden = NO;
}
else
{
iAd.hidden = YES;
}
}
}
Now, the problem is, when I test the app without internet connection the iAd does not load (obviously) BUT it also does not hide. So, at the top of the screen I'm left with a big white rectangle. Otherwise, the ad works fine when a connection is available. Does anyone have any ideas? Also - I just added the endless loops to see if they made a difference, those were completely on purpose lol.
I'm assuming you have added your ADBannerView via the Storyboard as I can't see where you initialise the banner position.
In storyboard, set the initial location just off screen.
In "bannerViewDidLoadAd", animate the banner into view.
In "bannerView: didFailToReceiveAdWithError:", animate the banner out of view.
There is a good example here https://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/iAd_Guide/WorkingwithBannerViews/WorkingwithBannerViews.html
Hope this helps. I have just implemented this but don't have access to my code at the moment.
It does bring up some errors in the simulator but works fine on a device.
I have tested this on iOS6 and works ok even if an iAd is displayed then the user loses the connection (so it looks like "bannerView: didFailToReceiveAdWithError:" is being called for me).
You have a property bannerLoaded for saving the state of your Ad, which is good.
At the very first, in your viewDidLoad method, iAd can't be loaded, so you have to set your property accordingly : self.bannerLoaded = NO;
Then, when you receive / fail to receive your ad, you need to update this property.
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
if (!self.bannerLoaded) {
iAd.hidden = NO;
self.bannerLoaded = YES;
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (self.bannerLoaded) {
iAd.hidden = YES;
self.bannerLoaded = NO;
}
}

iAd & Admob integration

I integrated iAd / Admob display code from the link from here: http://www.apptite.be/tutorial_mixing_ads.php
and had some weird results. On admob, my click through rate dropped 40%, but the number of impressions stayed the same. Its as if both ads are shown at the same time, with iAds on top of admob ads. Does anyone see problems with the code on that site that could possibly cause that?
Thank you in advance for your help.
Firstly we should download Admob Sdk from google.
That file is required In google AdMob API :-
GADAdSize.h
GADBannerView.h
GADBannerViewDelegate.h
GADInterstitial.h
GADInterstitial.h
GADRequest.h
GADRequestError.h
libGoogleAdMobAds
#import <UIKit/UIKit.h>
#import "GADBannerViewDelegate.h"
#class GADBannerView, GADRequest;
#interface BannerExampleViewController : UIViewController
<GADBannerViewDelegate> {
GADBannerView *adBanner_;
}
#property (nonatomic, retain) GADBannerView *adBanner;
- (GADRequest *)createRequest;
#end
#import "BannerViewController.h"
#import "GADBannerView.h"
#import "GADRequest.h"
#implementation BannerExampleViewController
#synthesize adBanner = adBanner_;
#pragma mark init/dealloc
// Implement viewDidLoad to do additional setup after loading the view,
// typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
CGPoint origin = CGPointMake(0.0,
self.view.frame.size.height -
CGSizeFromGADAdSize(kGADAdSizeBanner).height);
self.adBanner = [[[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner
origin:origin]
autorelease];
self.adBanner.adUnitID = AdMob key;
self.adBanner.delegate = self;
[self.adBanner setRootViewController:self];
[self.view addSubview:self.adBanner];
[self.adBanner loadRequest:[self createRequest]];
}
- (void)dealloc {
adBanner_.delegate = nil;
[adBanner_ release];
[super dealloc];
}
#pragma mark GADRequest generation
- (GADRequest *)createRequest {
GADRequest *request = [GADRequest request];
request.testing = YES;
return request;
}
#pragma mark GADBannerViewDelegate impl
- (void)adViewDidReceiveAd:(GADBannerView *)adView {
NSLog(#"Received ad successfully");
}
- (void)adView:(GADBannerView *)view
didFailToReceiveAdWithError:(GADRequestError *)error {
NSLog(#"Failed to receive ad with error: %#", [error localizedFailureReason]);
}
#end
Hmm, so I'm looking at the code that says:
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
NSLog(#"iAdBanner failed");
// Only request adMob when iAd did fail
[self adMobRequest];
And on Apple's site, it says that "Even after an error is sent to your delegate, the banner view continues to try to download new advertisements. Thus, implementing both of these delegate methods allows your application to display the banner only when advertisements are loaded." (link)
I'm guessing that what is happening is that if iAd fails, you're displaying an AdMob ad, but then iAd is also retrying as well and so if it fails again, it is requesting another AdMob ad despite the fact that one may already be getting shown?

Objective-C on iPhone - tab bar crash

I'm relatively new to Objective-C and coding. I've tried doing a little dev on my own but have now become stuck on what is probably a rookie error.
I've created a tab bar controller with 5 views, one such view is a UIWebView. I've got the Webview working and it loads, but when I select a different tab, the app crashes. Please find my code below and any help would be appreciated!
#import <UIKit/UIKit.h>
#interface LiveViewController : UIViewController {
IBOutlet UIWebView *liveView;
}
#property (nonatomic, retain) UIWebView *liveView;
#end
#import "LiveViewController.h"
#implementation LiveViewController
#synthesize liveView;
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[self.liveView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.britishseapower.co.uk/live/"]]];
[super viewDidLoad];
}
- (void)webViewDidStartLoad:(UIWebView *)liveView
{
// starting the load, show the activity indicator in the status bar
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)liveView
{
// finished loading, hide the activity indicator in the status bar
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void)liveView:(UIWebView *)liveView didFailLoadWithError:(NSError *)error
{
// load error, hide the activity indicator in the status bar
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// report the error inside the webview
NSString* errorString = [NSString stringWithFormat:
#"<html><center><font size=+5 color='red'>An error occurred:<br>%#</font></center></html>",
error.localizedDescription];
[self.liveView loadHTMLString:errorString baseURL:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
if ( [self.liveView loading] ) {
[self.liveView stopLoading];
}
self.liveView.delegate = nil; // disconnect the delegate as the webview is hidden
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void)dealloc {
[liveView release];
[UIWebView release];
[LiveViewController release];
[super dealloc];
}
#end
Many thanks,
Ryan
[UIWebView release]; [LiveViewController release];
This is what make your app crash.
It's not valid to send a release message to a class itself.
What you've done with [liveView release]; is enough (with the call to [super dealloc];.)
You should also set the delegate to nil in the dealloc method as in the viewWillDisappear method self.liveView.delegate = nil;. This way you're sure to avoid any further message sent to the LiveViewController from the UIWebView.
You should read a bit more of documentation on Objective-C to better understand how it works.
Not sure if this is related but I noticed that you aren't setting yourself as the delegate anywhere in code which means that it must be connected in Interface Builder. Now when the view disappears, you are breaking that connection, but if the view were to re-appear and wasn't previously unloaded that connection will remain broken.
One of the most common reasons why an app may crash is to refer to or send a message to an object that has been already released from the memory. And this type of bug can be easily located using NSZombieEnabled and looking into the console message. So if you haven't already tried that, that's the first thing you must do.
The problem could be in LiveViewController but could be in the other view controllers as well. I wouldn't believe the problem is 100% in LiveViewController because the view controller wouldn't try releasing its view when the view is not shown unless it gets a memory warning. And you run the app using the simulator, it's unlikely it will have a memory warning unless you simulate one.
You would probably know that a view controller never create a view unless the view is used by an object. One of the other view controllers may have a silly bug in its view loading process which causes a crash. Or, you might have released another view controller by mistake. Make 100% sure that the other view controllers have no problem showing their views on their own, when you keep changing between their views (without showing LiveViewController).
So what I would do is to try NSZombieEnabled and check if it accesses a released object, and if it does, what the object is. Also, I will make a double check that the problem is related to LiveViewController. If it doesn't help I would log a message when LiveViewController and its liveView is deallocated (for liveView you need to subclass it). Because delegate property almost always does not retain an object, if the LiveViewController object is released (which shouldn't happen) and liveView still has a reference to it in the delegate property it will make a crash.
Crashes like this are almost always related to releasing an object that has already been released and deallocated.
Let XCode help you find the error. In XCode 4:
- In the toolbar, select the scheme list, and select 'Edit Scheme'
- Select the 'Run Your.app' in the list on the left.
- Under 'Environment Variables', add the following name/value pairs in the appropriate columns:
CFZombieLevel 3
NSZombieEnabled YES
Now when debug your app, you will get a message telling when -release is called on an object that already has a -retainCount of zero. Now you have a good clue to start your investigation.
Note that these flags prevent objects from being deallocated, so it is best to turn them on as needed to prevent out of memory errors.

Crash in ABPeoplePicker when called from another modal viewcontroller and both dismissed

(Note: I filed this question before in the context of my project, but I've now recreated the crash in a test project. Any help in telling me what I'm doing wrong would be appreciated.)
The crash occurs when calling ABPeoplePicker from another modal viewcontroller. Specifically, the main window has a NavController, which loads myVC. myVC then loads a modal NavController containing my controller, which then calls ABPeoplePicker. In this demo program, no user intervention is necessary until ABPeoplePicker runs.
The crash occurs if you use the search box in the people picker, and then select one of the resulting people. (If you use the simulator, you'll need to add a person in Contacts before running the program.) The program returns, but during the dismissal of the two modal VCs, I get an assertion error crash. It occurs every time on iphone, ipad, and simulators for both. This seems a very normal thing to do, so I find it hard to believe this is a real bug. The crash message is:
Assertion failure in
-[ABMembersSearchDisplayController setActive:animated:],
/SourceCache/UIKit_Sim/UIKit-1448.69/UISearchDisplayController.m:589 2011-01-31 13:51:11.903
testcrasher2[26044:207] *
Terminating app due to uncaught
exception
'NSInternalInconsistencyException',
reason: 'search contents navigation
controller must not change between
-setActive:YES and -setActive:NO'
So to demonstrate, in a new Xcode iPhone Window application, I modify the didFinishLaunchingWithOptions to call my controller. Then I create two VCs as follows. (Note you need to add Addressbook frameworks to the target.) Here's the entire program...
AppDelegate.didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myViewController *detailViewController = [[myViewController alloc] init];
// Set the navigation controller as the window's root view controller and display.
UINavigationController * navController = [[UINavigationController alloc] initWithRootViewController: detailViewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
[detailViewController release];
[navController release];
return YES;
}
myViewController.h:
#interface myViewController : UIViewController<addDelegate>{
}
#end
myViewController.m:
#import "myViewController.h"
#import "AddNewViewController.h"
#implementation myViewController
- (void)controllerDidFinish:(addNewViewController *)controller {
[self dismissModalViewControllerAnimated:YES];
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear: animated];
addNewViewController *addController = [[addNewViewController alloc] init];
addController.delegate = self;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addController];
[self presentModalViewController:navController animated:YES];
[navController release];
[addController release];
}
#end
AddNewViewController.h:
#import <AddressBookUI/AddressBookUI.h>
#protocol addDelegate;
#interface addNewViewController : UIViewController < ABPeoplePickerNavigationControllerDelegate> {
id <addDelegate> delegate;
}
#property(nonatomic, assign) id <addDelegate> delegate;
#end
#protocol addDelegate <NSObject>
- (void)controllerDidFinish:(addNewViewController *)controller ;
#end
AddNewViewController.m:
#import "AddNewViewController.h"
#implementation addNewViewController
#synthesize delegate;
-(void) viewDidAppear:(BOOL)animated {
ABPeoplePickerNavigationController * peoplepicker = [[ABPeoplePickerNavigationController alloc] init] ;
peoplepicker.peoplePickerDelegate = self;
[self presentModalViewController:peoplepicker animated:YES];
[peoplepicker release];
}
#pragma mark AddressBook delegate methods
- (void)peoplePickerNavigationControllerDidCancel: (ABPeoplePickerNavigationController *)peoplePicker {
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
[self.delegate controllerDidFinish:self ];
return NO; //EDIT: This MUST be YES or it will crash (see answer below)
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier {
return NO;
}
#end
Turns out this is an actual bug. It is indeed true that if you do a double ModalVC dismiss to ABPeoplePicker when the user clicks a person in search, you'll get this crash. Fortunately, there's a simple workaround: return YES in your delegate's shouldContinueAfterSelectingPerson. As you're simultaneously dismissing the picker, it doesn't really matter whether you return YES or NO, it won't continue, but NO will crash and YES doesn't. (Same answer as for my original post: Weird crash in ABPeoplePicker )
The bug is in fact in your code. Took me a few minutes to find it, I'll try to explain as best I can.
Your
ABPeoplePickerNavigationController
is currently presented modally.
You click in the search bar and type
some stuff.
You click a person's name.
What happens here, is the ABPeoplePickerNavigationController asks its delegate (which is your addNewViewController) whether it should continue after selecting a person. While it's waiting to hear back from you, you suddenly call your own protocol's method (in myViewController) that attempts to dismiss the modal addNewViewController. You're jumping ahead of yourself, as the ABPeoplePickerNavigationController is still open.
Change your implementation of the ABPeoplePickerNavigationControllerDelegate method to read:
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
// This line is new.
[self.navigationController dismissModalViewControllerAnimated:YES];
[self.delegate controllerDidFinish:self];
return NO;
}
And your crash will go away. When you're dealing with layers upon layers of UIViewControllers and UINavigationControllers, you have to be very careful to dismiss them in the reverse order you presented them.