UITableView scrolling under iAd - ios

i want to display iAd at the bottom of the screen..
i tried to add subView but the iAd showed in a cell and he hides him.
what should i do to make the tableView to scroll under the iAd?
my code:
- (void)viewDidLoad
{
[super viewDidLoad];
[self createAdBannerView];
[self.view addSubview:self.adBannerView];
}
#pragma mark - ADBannerViewDelegate
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
[self adjustBannerView];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
[self adjustBannerView];
}
- (BOOL)bannerViewActionShouldBegin:(ADBannerView *)banner willLeaveApplication:(BOOL)willLeave
{
return YES;
}
- (void)bannerViewActionDidFinish:(ADBannerView *)banner
{
}
- (void) adjustBannerView
{
CGRect contentViewFrame = self.view.bounds;
CGRect adBannerFrame = self.adBannerView.frame;
if([self.adBannerView isBannerLoaded])
{
CGSize bannerSize = [ADBannerView sizeFromBannerContentSizeIdentifier:self.adBannerView.currentContentSizeIdentifier];
contentViewFrame.size.height = contentViewFrame.size.height - bannerSize.height;
adBannerFrame.origin.y = contentViewFrame.size.height;
}
else
{
adBannerFrame.origin.y = contentViewFrame.size.height;
}
[UIView animateWithDuration:0.5 animations:^{
self.adBannerView.frame = adBannerFrame;
self.contentView.frame = contentViewFrame;
}];
}
- (void) createAdBannerView
{
self.adBannerView = [[ADBannerView alloc] initWithFrame:CGRectZero];
CGRect bannerFrame = self.adBannerView.frame;
bannerFrame.origin.y = self.view.frame.size.height;
self.adBannerView.frame = bannerFrame;
self.adBannerView.delegate = self;
self.adBannerView.requiredContentSizeIdentifiers = [NSSet setWithObjects:ADBannerContentSizeIdentifierPortrait, ADBannerContentSizeIdentifierLandscape, nil];
}
EDIT:
How do I prevent this?
i want to keep the iAd at the botton..
thanks in advance!

If you're using auto layout, what I've done before is add an outlet to the constraint for the bottom space to superview (assuming you have a tableview within a view).
You can then just adjust the constraint in the callback when the ad is loaded by for example doing
tableViewBottomSpaceConstraintOutlet.constant -= adBannerView.frame.size.height;
where tableViewBottomSpaceConstraintOutlet is the outlet on the bottom space to superview constraint and adBannerView is your ad banner's view.

Suggestion from Apple is to add a container view to contain the ScrollView(TableView) and setup constraints between the fixed view and the container view
details here:
Using Scroll Views with Auto Layout

Related

iAd is white (not loaded) when application starts

My iAd is white. It looks like bannerViewDidLoadAd is run when the iAd is not fully loaded. It happens only when I show my ViewController first time (application starts). When I go to another controller and return, iAd is loaded properly. Do you have any idea why?
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
_bannerView.hidden = NO;
[self.view setNeedsLayout];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
_bannerView.hidden = YES;
[self.view setNeedsLayout];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (!_bannerView) {
_bannerView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
_bannerView.delegate = self;
_bannerView.hidden = YES;
CGRect bannerFrame = _bannerView.frame;
bannerFrame.origin.y = self.view.bounds.size.height - _bannerView.bounds.size.height;
_bannerView.frame = bannerFrame;
[self.view addSubview:_bannerView];
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
_bannerView.delegate = nil;
[_bannerView removeFromSuperview];
_bannerView = nil;
}

iOS: iAd Singleton Confusion

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.

iAd get screwed up on ipad simulator

currently I'm trying to implement iAd in my universal iOS7 app.
This is working absolutly fine on iphone but on the ipad i get this screwed up ads but the bannersize is correct.
is this a known issue? or is there a ipad special implementation I didn't knew?
[edit!]
I'm pretty sure there is only one banner! its really just showing the normal iad ad in that weird way.
If I click on the ad, the fullscreen one is also not right scaled but its shown on the hole screen. Here is my implementation:
- (void)viewDidLoad
{
_adBannerView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
_adBannerView.delegate = self;
_bannerIsVisible = NO;
[self.view addSubview:self.adBannerView];
...
}
- (void)viewDidLayoutSubviews {
CGRect contentFrame = _mainNavigation.frame, bannerFrame = CGRectZero;
bannerFrame.size = [_adBannerView sizeThatFits:contentFrame.size];
if (_adBannerView.bannerLoaded && !_bannerIsVisible) {
contentFrame.size.height -= bannerFrame.size.height;
bannerFrame.origin.y = contentFrame.origin.y + contentFrame.size.height;
_bannerIsVisible = YES;
} else {
bannerFrame.origin.y = contentFrame.origin.y + contentFrame.size.height;
}
_mainNavigation.frame = contentFrame;
_adBannerView.frame = bannerFrame;
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
[UIView animateWithDuration:0.25 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
NSLog(#"didFailToReceiveAdWithError %#", error);
[UIView animateWithDuration:0.25 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];
}
And is there a way to show the test ads on a real device?
because I always get "Ad inventory unavailable"!

How to add iAd in Cocos-SpriteBuilder

I am using SpriteBuilder (which integrates with Cocos2d v3.0). I built an app and now I want to put in an iAd at the very top that pops up when I call it, and hides when I tell it to. What's the simplest way to do this?
Keep in mind I am using SpriteBuilder with Cocos2d. And just because I am using SpriteBuilder does not mean I am not using Xcode 5 as well. I am fully involved in Xcode as well. SpriteBuilder does not write the code for me, I do that.
Add iAd framework to your dependencies.
In your header file for your game scene, add the ADBannerViewDelegate, for instance:
#interface MainScene : CCNode <CCPhysicsCollisionDelegate, ADBannerViewDelegate>
In your implementation file, add the instance variable _bannerView:
#implementation MainScene {
ADBannerView *_bannerView;
}
And finally, insert the the iAD code (with some cocos2d tweaks). Here's my implementation for a game in portrait mode with a top banner. There's no hide method, but it's pretty easy to implement.
# pragma mark - iAd code
-(id)init
{
if( (self= [super init]) )
{
// On iOS 6 ADBannerView introduces a new initializer, use it when available.
if ([ADBannerView instancesRespondToSelector:#selector(initWithAdType:)]) {
_adView = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
} else {
_adView = [[ADBannerView alloc] init];
}
_adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
_adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
[[[CCDirector sharedDirector]view]addSubview:_adView];
[_adView setBackgroundColor:[UIColor clearColor]];
[[[CCDirector sharedDirector]view]addSubview:_adView];
_adView.delegate = self;
}
[self layoutAnimated:YES];
return self;
}
- (void)layoutAnimated:(BOOL)animated
{
// As of iOS 6.0, the banner will automatically resize itself based on its width.
// To support iOS 5.0 however, we continue to set the currentContentSizeIdentifier appropriately.
CGRect contentFrame = [CCDirector sharedDirector].view.bounds;
if (contentFrame.size.width < contentFrame.size.height) {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
CGRect bannerFrame = _bannerView.frame;
if (_bannerView.bannerLoaded) {
contentFrame.size.height -= _bannerView.frame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
bannerFrame.origin.y = contentFrame.size.height;
}
[UIView animateWithDuration:animated ? 0.25 : 0.0 animations:^{
_bannerView.frame = bannerFrame;
}];
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
[self layoutAnimated:YES];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
[self layoutAnimated:YES];
}

How to show app-specific status bar at bottom of screen, outside of app?

I have a requirement to show a status bar at certain times at the bottom of my application. I can easily put this at the bottom of my application's main view, but whenever I push a view controller on top of this (either modally or not) it hides this status bar.
Is there any way I can add a status bar like this, and have it be outside the bounds of my application itself? Ideally I'd like this to work like the call-in-progress status bar on the iPhone - when this bar appears, the app is pushed down, and a call to [[UIScreen mainScreen] applicationFrame] returns the correct size (i.e. it accounts for the presence of this status bar when calculating the height available for the app).
I wanted to do this, too, so I tried View Controller Containment. I'm still trying it out, so I'm not willing to give this a ringing endorsement, but it might be something you'd want to try playing around with yourself if you're in iOS5. But it appears to give you a status bar that will appear or disappear from the bottom of the screen.
This is a view controller that will open another view controller, but if there is status text to show, it pops up from the bottom of the screen and stays there until you get rid of it. I've only done a little testing so far, but it looks like this handles pushViewController/popViewController, but maybe not modal views.
My header looks like:
// StatusBarViewController.h
//
// Created by Robert Ryan on 7/8/12.
#import <UIKit/UIKit.h>
#interface StatusBarViewController : UIViewController
#property (strong, nonatomic) UIViewController *appController;
- (void)setStatus:(NSString *)text;
#end
My implementation file (this is ARC) looks like:
// StatusBarViewController.m
//
// Created by Robert Ryan on 7/8/12.
#import "StatusBarViewController.h"
#interface StatusBarViewController ()
{
BOOL _statusHidden;
UIView *_appView;
UILabel *_statusLabel;
}
#end
#implementation StatusBarViewController
#synthesize appController = _appController;
- (void)dealloc
{
_appView = nil;
_statusLabel = nil;
[self setAppController:nil]; // usually I don't like setters in dealloc, but this does some special stuff
}
- (void)createControlsWithStatusHidden
{
// create default app view that takes up whole screen
CGRect frame = self.view.frame;
frame.origin = CGPointMake(0.0, 0.0);
_appView = [[UIView alloc] initWithFrame:frame];
_appView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_appView.clipsToBounds = YES;
[self.view addSubview:_appView];
// create status label that is just off screen below the app view
_statusLabel = [[UILabel alloc] init];
_statusLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:12.0];
_statusLabel.backgroundColor = [UIColor darkGrayColor];
_statusLabel.textColor = [UIColor whiteColor];
CGSize size = [#"Hey!" sizeWithFont:_statusLabel.font]; // test size of box with random text
_statusLabel.frame = CGRectMake(0.0, frame.size.height, frame.size.width, size.height);
_statusLabel.textAlignment = UITextAlignmentCenter;
_statusLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
[self.view addSubview:_statusLabel];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self createControlsWithStatusHidden];
_statusHidden = YES;
// I'm instantiating from storyboard. If you're using NIBs, just create your controller controller using initWithNib and then set our appController accordingly.
self.appController = [self.storyboard instantiateViewControllerWithIdentifier:#"MainNavigator"];
}
- (void)setAppController:(UIViewController *)controller
{
if (controller)
{
controller.view.frame = CGRectMake(0.0, 0.0, _appView.frame.size.width, _appView.frame.size.height);
[self addChildViewController:controller];
[controller didMoveToParentViewController:self];
if (self.appController)
{
// if we have both a new controller and and old one, then let's transition, cleaning up the old one upon completion
[self transitionFromViewController:self.appController
toViewController:controller
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionCurveEaseInOut
animations:nil
completion:^(BOOL finished){
if (self.appController)
{
[self.appController willMoveToParentViewController:nil];
[self.appController removeFromParentViewController];
}
}];
}
else
{
// if we have no previous controller (i.e. this is our first rodeo), then just add it to the view
[_appView addSubview:controller.view];
}
}
else
{
// no new controller, so we're just removing any old on if it was there
if (self.appController)
{
// if there was an old controller, remove it's view, and remove it from the view controller hierarchy
[self.appController.view removeFromSuperview];
[self.appController willMoveToParentViewController:nil];
[self.appController removeFromParentViewController];
}
}
_appController = controller;
}
- (void)hideStatusWithCompletion:(void (^)(BOOL finished))completion
{
[UIView animateWithDuration:0.25
animations:^{
CGRect labelFrame = _statusLabel.frame;
labelFrame.origin.y += labelFrame.size.height;
_statusLabel.frame = labelFrame;
CGRect appFrame = _appView.frame;
appFrame.size.height += labelFrame.size.height;
_appView.frame = appFrame;
}
completion:completion];
}
- (void)unhideStatusWithCompletion:(void (^)(BOOL finished))completion
{
[UIView animateWithDuration:0.25
animations:^{
CGRect labelFrame = _statusLabel.frame;
labelFrame.origin.y -= labelFrame.size.height;
_statusLabel.frame = labelFrame;
CGRect appFrame = _appView.frame;
appFrame.size.height -= labelFrame.size.height;
_appView.frame = appFrame;
}
completion:completion];
}
- (void)setStatus:(NSString *)text
{
BOOL hasText = (text && [text length] > 0);
if (hasText)
{
if (!_statusHidden)
{
// if we have text, but status is already shown, then hide it and unhide it with new value
[self hideStatusWithCompletion:^(BOOL finished){
_statusLabel.text = text;
[self unhideStatusWithCompletion:nil];
}];
}
else
{
// if we have text, but no status is currently shown, then just unhide it
_statusLabel.text = text;
[self unhideStatusWithCompletion:nil];
}
_statusHidden = NO;
}
else
{
if (!_statusHidden)
{
// if we don't have text, but status bar is shown, then just hide it
[self hideStatusWithCompletion:^(BOOL finished){
_statusLabel.text = text;
}];
_statusHidden = YES;
}
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
And then, any view controller that wants to update the status message would use a method kind of like:
- (void)setStatus:(NSString *)text
{
UIViewController *controller = [UIApplication sharedApplication].delegate.window.rootViewController;
if ([controller isKindOfClass:[StatusBarViewController class]])
{
[(StatusBarViewController *)controller setStatus:text];
}
}

Resources