I have a strange problem. iAds work. As soon as I initialize a UIButton (using "[self initCloseAdButtonWithFrame:_frame];") The iAds stop working, while the button is initialized in the correct place. This code slides an ad banner in and out depending on the availability of the ad.
Why is the initialization of closeButton breaking the ads functionality?
ViewController.m
#pragma mark - Ads
-(void)initiAdBanner
{
DLog(#"");
if (!self.iAdBannerView)
{
CGRect rect = CGRectMake(0, self.view.frame.size.height, 0, 0);
self.iAdBannerView = [[ADBannerView alloc]initWithFrame:rect];
self.iAdBannerView.delegate = self;
self.iAdBannerView.hidden = TRUE;
[self.view addSubview:self.iAdBannerView];
}
}
#pragma mark - ADBanner delegate methods -
// Called before the add is shown, time to move the view
- (void)bannerViewWillLoadAd:(ADBannerView *)banner
{
DLog(#"iAd load");
[self hideBanner:self.gAdBannerView];
[self showBanner:self.iAdBannerView];
}
// Called when an error occured
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
DLog(#"iAd error: %#", error);
[self hideBanner:self.iAdBannerView];
GADRequest *request = [GADRequest request];
request.testDevices = [NSArray arrayWithObjects:GAD_SIMULATOR_ID, nil];
[self.gAdBannerView loadRequest:request];
}
#pragma mark - Banner hide and show -
// Hide the banner by sliding down
-(void)hideBanner:(UIView*)banner
{
if (banner && ![banner isHidden])
{
[UIView beginAnimations:#"hideBanner" context:nil];
banner.frame = CGRectOffset(banner.frame, 0, banner.frame.size.height);
[UIView commitAnimations];
banner.hidden = TRUE;
if(closeButton){
[closeButton setHidden:TRUE];
}
}
}
// Show the banner by sliding up
-(void)showBanner:(UIView*)banner
{
if (banner && [banner isHidden])
{
CGRect _frame2 = CGRectOffset(banner.frame, 0, -banner.frame.size.height);
CGRect _frame = CGRectOffset(banner.frame, 0, -banner.frame.size.height);
[self initCloseAdButtonWithFrame:_frame];
[UIView beginAnimations:#"showBanner" context:nil];
banner.frame = _frame2;
[UIView commitAnimations];
banner.hidden = FALSE;
}
}
//button initialize
-(void)initCloseAdButtonWithFrame:(CGRect)frame{
DLog(#"");
closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[closeButton addTarget:self
action:#selector(inAppPurchase)
forControlEvents:UIControlEventTouchUpInside];
UIImage *_closeImage = [UIImage imageNamed:#"closeButton.png"];
UIImage *closeImage = [UIImage imageWithCGImage:_closeImage.CGImage scale:_closeImage.scale orientation:UIImageOrientationDown];
[closeButton setBackgroundImage:closeImage forState:UIControlStateNormal];
[closeButton setBackgroundImage:closeImage forState:UIControlStateHighlighted];
closeButton.frame = CGRectMake(frame.size.width - closeImage.size.width, -5 + self.view.frame.size.height -frame.size.height - closeImage.size.height, closeImage.size.width, closeImage.size.height);
[self.view insertSubview:closeButton atIndex:2];
[closeButton setHidden:FALSE];
}
-(void)inAppPurchase{
DLog(#"");
}
ShowBanner is called via a delegate of iAd. In Show banner, the button is initialized. The code works (ads show up) only if the button is not initialized.
In particular, everything works fine until the button is added to the subview.
The issue is - you are using the same frame to show button and the banner. As a result, the button is covering it fully. Reduce _frame.size.height inside showBanner function and you will see the banner.
Related
I'm trying to handle my iAd via a singleton, since I'm using these banners in several view controllers. Now I'm confused of what do these objects store, since I move them around differently on each view controller when an ad is shown or if an error occured. Here my code:
Singleton:
+ (MySingleton *)sharedInstance {
static dispatch_once_t once;
static MySingleton * sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (id)init
{
if (self = [super init]) {
if ([ADBannerView instancesRespondToSelector:#selector(initWithAdType:)]) {
self.bannerView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
} else {
self.bannerView = [[ADBannerView alloc] init];
}
}
return self;
}
And here how it is initalized:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
//iAd
if(![[NSUserDefaults standardUserDefaults] objectForKey:kInAppPurchaseNoAds]){
self.bannerView = [MySingleton sharedInstance].bannerView;
self.bannerView.delegate = self;
self.bannerView.frame = CGRectOffset(self.bannerView.frame, 0, self.view.frame.size.height);
[self.view addSubview:self.bannerView];
}
}
And the delegate methods:
- (void)showBanner
{
if(!self.isBannerVisible){
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.5
animations:^{
//Restore the constraint
self.mainContainerToSuperviewConstraint.constant = 50;
//Move the banner on
self.bannerView.frame = CGRectOffset(self.bannerView.frame, 0, -50);
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
self.isBannerVisible = YES;
}];
}
}
- (void)hideBanner
{
if(self.isBannerVisible){
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.5
animations:^{
//Restore the constraint
self.mainContainerToSuperviewConstraint.constant = 0;
//Move the banner off
self.bannerView.frame = CGRectOffset(self.bannerView.frame, 0, self.bannerView.frame.size.height);
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
self.isBannerVisible = NO;
}];
}
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
[self showBanner];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
[self hideBanner];
}
Now what I'm confused is, do I have to check the position of the banner view again if the user was in another view with also an iAd where the rectangle with visible banner was at let's say 75 from the bottom of the screen and not 50? Or do these positions do not influence the AdBannerView but only the single object in each class?! I mean if he was in the other view and there the code moved the Banner to 75 pixels from the bottom, are these 75 pixels stored in my singleton AdView? So the original view had the banner now at 75 and not at 50?
I would suggest against having a singleton for a view - one view instance can be a subview only of 1 view, so you need to track adding/removing it and also you need to set the frame every time you add it again as a subview. You better have some kind of base view controller to share the instantiation logic and the control of the banners.
In my app, I had added the ADBannerView into the UIViewController by code
in .h file
#property (strong, nonatomic) ADBannerView *adBannerView;
in .m file
- (void)viewDidLoad
{
[super viewDidLoad];
self.adBannerView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, 518, 320, 50);];
[self.view addSubview:self.adBannerView];
}
#pragma mark - 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 {
NSLog(#"banner action should begin");
return YES;
}
- (void)bannerViewWillLoadAd:(ADBannerView *)banner {
NSLog(#"banner will loaded");
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
NSLog(#"banner was loaded");
}
My app is normally, it can show the ADBannerView. But now, I want to remove the ADBannerView out of the UIViewController, then I removed all the lines of code about the ADBannerView. I can build my app, but it cannot run, the error msg is:
Could not instantiate class named ADBannerView
Please help me to remove the ADBannerView. Thank you.
- (void)bannerViewDidLoadAd:(ADBannerView *)banner{
if (!bannerIsVisible){
//LOG_TYPE(#"AD show");
[UIView beginAnimations:#"animateAdBannerOn" context:NULL];
// banner is invisible now and moved out of the screen on 50 px
// banner.frame = CGRectOffset(banner.frame, 0, -50);
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
if (IS_IPHONE_5) {
//LOG_TYPE(#"view height: %f",self.view.bounds.size.height);
self.adView.frame = CGRectMake(0,568-49-50, self.view.frame.size.width, 50);
}
else{
//LOG_TYPE(#"view height: %f",self.view.bounds.size.height);
self.adView.frame = CGRectMake(0,480-49-50, self.view.frame.size.width, 50);
}
}
else{
self.adView.frame = CGRectMake(0,1024-56-50, self.view.frame.size.width, 50);
}
[UIView commitAnimations];
bannerIsVisible = YES;
[self performSelector:#selector(hideAD) withObject:nil afterDelay:6];
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error{
if (bannerIsVisible){
//LOG_TYPE(#"AD error");
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
// banner is visible and we move it out of the screen, due to connection issue
// banner.frame = CGRectOffset(banner.frame, 0, 50);
bannerIsVisible = NO;
[self performSelector:#selector(hideAD) withObject:nil afterDelay:0];
// [self performSelector:#selector(hideAD) withObject:nil afterDelay:5];
}
}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave{
//LOG_TYPE(#"Banner view is beginning an ad action");
BOOL shouldExecuteAction = YES;
if (!willLeave && shouldExecuteAction){
// stop all interactive processes in the app
// [video pause];
// [audio pause];
}
return shouldExecuteAction;
}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner{
// resume everything you've stopped
// [video resume];
// [audio resume];
}
- (void)hideAD{
//LOG_TYPE(#"Hide AD");
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
// banner is visible and we move it out of the screen, due to connection issue
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
if (IS_IPHONE_5) {
//LOG_TYPE(#"view height: %f",self.view.bounds.size.height);
self.adView.frame = CGRectMake(0,568-49+50, self.view.frame.size.width, 50);
}
else{
//LOG_TYPE(#"view height: %f",self.view.bounds.size.height);
self.adView.frame = CGRectMake(0,480-49+50, self.view.frame.size.width, 50);
}
}
else{
self.adView.frame = CGRectMake(0,1024-56+50, self.view.frame.size.width, 50);
}
[UIView commitAnimations];
bannerIsVisible = NO;
[self performSelector:#selector(bannerViewDidLoadAd:) withObject:self.adView afterDelay:60];
}
-(void)viewDidLoad{
...
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone){
if (IS_IPHONE_5) {
self.adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0,568-49-50, self.view.frame.size.width, 50)];
}
else{
self.adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0,480-49-50, self.view.frame.size.width, 50)];
}
}
else{
self.adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0,1024-56-50, self.view.frame.size.width, 50)];
}
[self.view addSubview:self.adView];
self.adView.delegate=self;
bannerIsVisible=NO;
self.adView.backgroundColor = [UIColor clearColor];
....
}
if you add ADBannerView in storyboard then remove the IBoutlet of ADBannerView and its delegate.
break connection of below figure for ADBannerView
remove ADBannerViewfrom storyboard and your above code is perfect.
Your error as below.
[self.adView removeFromSuperView];
I am trying to create 2 iAds but I have only one on simulator. I can not now check it with device. Why I have only one? I have only second iAd
My code is:
adView1 = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
adView1.frame = CGRectOffset(adView1.frame, 0, 50);
adView1.delegate = self;
[self.backgroundView addSubview:adView1];
adView2 = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
adView2.frame = CGRectOffset(adView2.frame, 0, 200);
adView2.delegate = self;
[self.backgroundView addSubview:adView2];
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
if (!self.bannerIsVisible)
{
[UIView beginAnimations:#"animateAdBannerOn" context:NULL];
// banner is invisible now and moved out of the screen on 50 px
if (banner == adView1)
{
banner.frame = CGRectOffset(banner.frame, 0, 50);
}
if (banner == adView2)
{
banner.frame = CGRectOffset(banner.frame, 0, 200);
}
[UIView commitAnimations];
self.bannerIsVisible = YES;
}
}
(void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (self.bannerIsVisible)
{
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
// banner is visible and we move it out of the screen, due to connection issue
banner.frame = CGRectOffset(banner.frame, 0, -50);
[UIView commitAnimations];
self.bannerIsVisible = NO;
}
}
(BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
NSLog(#"Banner view is beginning an ad action");
BOOL shouldExecuteAction = YES;
if (!willLeave && shouldExecuteAction)
{
[audio pause];
}
return shouldExecuteAction;
}
(void)bannerViewActionDidFinish:(ADBannerView *)banner
{
[audio resume];
}
adView1.frame = CGRectOffset(adView2.frame, 0, 50);
It must be CGRectOffset(adView1.frame, 0, 50); since adView2 is allocation in the next line only???
When you are creating first view, you are using second view's frame:
adView1 = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
adView1.frame = CGRectOffset(adView2.frame, 0, 50);
adView1.delegate = self;
[self.backgroundView addSubview:adView1];
As adView2 is not created yet - it is nil and frame is (0,0,0,0)
You have to use adView1 frame for offset as you do for second view.
Also, keep in mind that displaying 2 banners is going against Apple guideline and not recommend. Take a look here (Best practices section)
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/iAd_Guide/WorkingwithBannerViews/WorkingwithBannerViews.html
Integrated the Rev Mob banner type Ad with my iOS app.It was successfully displayed the Ads of banner type.
But I want to change the banner position to top of the screen.How can I change the position of banner type Ad to top?
For displaying the banner type Ad I used the following code,
[[RevMobAds session] showBanner];
You can always use a UIView to put the banner into. In banner load delegate, resize your intermediate view to banner's bounds.
In your ViewDidLoad Declare :-
ad = [[[RevMobAds session] bannerView] retain];
ad.delegate = self;
[ad loadAd];
Then add a method
- (void)revmobAdDidReceive {
intermediateView.frame = CGRectMake(0,0, somewidth, someheight);
ad.frame = intermediateView.bounds;
[intermediateView addSubview:ad];
}
Or simply set the frame accordingly.
RevMobBannerView *ad = [[RevMobAds session] bannerView];
ad.delegate = self;
[ad loadAd];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
ad.frame = CGRectMake(0, 0, 768, 114);
} else {
ad.frame = CGRectMake(0, 0, 320, 50);
}
[self.view addSubView:ad];
From their documentation (and it works well for me) :
RevMobBannerView *banner = [[RevMobAds session] bannerView];
banner.delegate = self;
[banner loadWithSuccessHandler:^(RevMobBannerView *banner) {
[banner setFrame:CGRectMake(10, 20, 200, 40)];
[self.view addSubview:banner];
NSLog(#"Ad loaded");
} andLoadFailHandler:^(RevMobBannerView *banner, NSError *error) {
NSLog(#"Ad error: %#",error);
} onClickHandler:^(RevMobBannerView *banner) {
NSLog(#"Ad clicked");
}];
My app shows articles from an RSS feed in a table view then when you select a row, opens a web view controller to show the article. I'm trying to add a loading indicator. If I select a row, the indicator will show briefly and then disappear before the page is fully loaded. Also, if I go back to the table view and select a different row, the loading indicator never shows up. I'm using a custom loading indicator called SVProgressHUD and it works fine elsewhere in the app. I don't think that is the problem though. What am I doing wrong?
Here is my didSelectRowAtIndexPath method in my table view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[webViewController webView]loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"about:blank"]]];
[self.navigationController pushViewController:webViewController animated:YES];
// Grab the selected item
RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView]loadRequest:req];
webViewController.hackyURL = url;
}
The loading indicator is started on this line in viewDidLoad of the WebViewController:
[SVProgressHUD showWithStatus:#"Loading"];
And here is my WebViewController.
#import "WebViewController.h"
#import "TUSafariActivity.h"
#import "SVProgressHUD.h"
#implementation WebViewController
#synthesize webView=webView, hackyURL=hackyURL;
- (void)loadView
{
// Create an instance of UIWebView as large as the screen
CGRect screenFrame = [[UIScreen mainScreen]applicationFrame];
UIWebView *wv = [[UIWebView alloc]initWithFrame:screenFrame];
webView = wv;
NSLog(#"%#",webView.request.URL);
// Tell web view to scale web content to fit within bounds of webview
[wv setScalesPageToFit:YES];
[self setView:wv];
}
- (UIWebView *)webView
{
return (UIWebView *)[self view];
}
- (void) showMenu
{
NSURL *urlToShare = hackyURL;
NSArray *activityItems = #[urlToShare];
TUSafariActivity *activity = [[TUSafariActivity alloc] init];
__block UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:activityItems applicationActivities:#[activity]];
activityVC.excludedActivityTypes = #[UIActivityTypeAssignToContact, UIActivityTypePostToWeibo, UIActivityTypeSaveToCameraRoll];
[self presentViewController:activityVC animated:YES completion:^{activityVC.excludedActivityTypes = nil; activityVC = nil;}];
}
- (void)toggleBars:(UITapGestureRecognizer *)gesture
{
BOOL barsHidden = self.navigationController.navigationBar.hidden;
if (!barsHidden)
{
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[self hideTabBar:self.tabBarController];
}
else if (barsHidden)
{
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[self showTabBar:self.tabBarController];
}
[self.navigationController setNavigationBarHidden:!barsHidden animated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[SVProgressHUD showWithStatus:#"Loading"];
UIBarButtonItem *systemAction = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(showMenu)];
self.navigationItem.rightBarButtonItem = systemAction;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(toggleBars:)];
[webView addGestureRecognizer:singleTap];
singleTap.delegate = self;
// self.hidesBottomBarWhenPushed = YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (void) hideTabBar:(UITabBarController *) tabbarcontroller
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
float fHeight = screenRect.size.height;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
{
fHeight = screenRect.size.width;
}
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
view.backgroundColor = [UIColor blackColor];
}
}
[UIView commitAnimations];
}
- (void) showTabBar:(UITabBarController *) tabbarcontroller
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
float fHeight = screenRect.size.height - 49.0;
if( UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) )
{
fHeight = screenRect.size.width - 49.0;
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, fHeight)];
}
}
[UIView commitAnimations];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//stop the activity indicator when done loading
[SVProgressHUD dismiss];
}
#end
You should use the delegate functions of a webview see below
-(void)webViewDidStartLoad:(UIWebView *)webView{
//SHOW HUD
}
-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
//KILL HUD
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
if(!webView.loading){
//KILL HUD
}
}
In webview normally caching happens, so HUD might not show for long as it will show for the first load.
I hope it will help you.
This is fixed. I just had to add
webView.delegate = self;