- (void)viewDidLoad
{
adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
CGRect adFrame = adView.frame;
adFrame.origin.y = self.view.frame.size.height-adView.frame.size.height;
adView.frame = adFrame;
[self.view addSubview:adView];
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
if (!self.bannerIsVisible)
{
self.bannerIsVisible = YES;
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
if (self.bannerIsVisible)
{
self.bannerIsVisible = NO;
}
There are a four things. First, you should be positioning the banner off screen in your viewDidLoad method because it will just show an empty frame when you first launch and will more than likely get rejected because of it.
Secondly, you are setting up your banner view incorrectly. I think the frame is still CGZero. Thirdly you are not setting the bannerView's delegate. Try the following:
-(void)viewDidLoad{
CGRect frame=CGRectZero;
frame.size = [ADBannerView sizeFromBannerContentSizeIdentifier:ADBannerContentSizeIdentifierPortrait];
// Place frame at the bottom edge of the screen out of sight
frame.origin = CGPointMake(0.0, CGRectGetMaxY(self.view.bounds));
// Now to create and configure the banner view
ADBannerView *adView = [[ADBannerView alloc] initWithFrame:frame];
adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
// Set the delegate to self, so that we are notified of ad responses
adView.delegate = self;
[self.view addSubview: adView];
}
Fourth, in your bannerViewDidLoadAd: method you are not animating the banner ad into place. Try this:
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
// Get a brand new frame
CGRect newFrame=CGRectZero;
CGPoint frameOrigin=CGPointZero;
// Set the origin
frameOrigin=CGPointMake(0.0, CGRectGetMaxY(self.view.bounds));
newFrame.origin=frameOrigin;
// Set the size
newFrame.size=[ADBannerView sizeFromBannerContentSizeIdentifier:ADBannerContentSizeIdentifierPortrait];
CGFloat bannerHeight = newFrame.size.height;
CGFloat bannerOffset=0.0;
// Determine where the new frame should be
if (!self.bannerIsVisible)
{
// It should be visible, raise it up
bannerOffset=-bannerHeight;
}
CGRect offSetRect=CGRectOffset(newFrame,0.0f,bannerOffset);
[UIView animateWithDuration:0.2
animations:^{banner.view.frame=offSetRect}
completion:^(BOOL finished){
if (bannerOffSet<0){
self.bannerIsVisible=YES;
}else{
self.bannerIsVisible=NO;
}
}
];
}
of course if the banner is supposed to be positioned at the top of the screen, you can probably figure out how things need to be modified, but this gets you in going in the right direction.
Good luck
Not sure by reading your question, but do be aware that Apple simulates iAds not being available. Sometimes you need to try multiple times before the sample ad comes through.
Related
I have a iPad app with 2 view controllers; 1st one is for the UI, the 2nd for a view which displays help from a UIWebView. When I go back and forth 10 times between view controllers, I get the message in the title above on exactly the 10th time returning to the first VC.
This is my code in VC #1:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
adView = [[ADBannerView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 50, 320, 50)];
_adBanner = [[ADBannerView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height, 320, 50)];
_adBanner.delegate = self;
[self.view addSubview:adView];
}
- (void) viewWillDisappear:(BOOL)animated {
[_adBanner removeFromSuperview];
_adBanner.delegate = nil;
_adBanner = nil;
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner {
if (!_bannerIsVisible) {
// If banner isn't part of view hierarchy, add it
if (_adBanner.superview == nil)
[self.view addSubview:_adBanner];
// }
[UIView beginAnimations:#"animateAdBannerOn" context:NULL];
// Assumes the banner view is just off the bottom of the screen.
banner.frame = CGRectOffset(banner.frame, 0, -banner.frame.size.height);
[UIView commitAnimations];
_bannerIsVisible = YES;
}
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error {
NSLog(#"Failed to retrieve ad");
if (_bannerIsVisible) {
[UIView beginAnimations:#"animateAdBannerOff" context:NULL];
// Assumes the banner view is placed at the bottom of the screen.
banner.frame = CGRectOffset(banner.frame, 0, banner.frame.size.height);
[UIView commitAnimations];
_bannerIsVisible = NO;
}
}
I know why, just don't know how to fix it. Can someone please help me with this?
You create an instance of ADBannerView in viewDidAppear and assign it to adView You don't appear do anything with this and more relevantly don't discard it in viewWillDisappear so each time you pop back to this view controller the previous instance is orphaned when you cycle through viewDidAppear.
Also possibly another issue is that you are not calling [super viewWillDisappear:] in your viewWillDisappear method.
Background
I've made a custom segue to allow for "overlay cards" to slide down from the top, and then fly away upon dismissal. When writing the code, I realized that all examples used a UIViewControllerTransitioningDelegate to capture when the segue was animate/dismissed. So far so good, but all examples that I found let the presentingController act as the delegate, which to me sounds strange since I need to "distribute" the logics of how my "overlay card" looks like, in two places; the custom segue, and the presenting controller.
Hence, I figured that I could combine the two into one; the custom segue, which would make my storyboard so much neater, since all view-controllers that I want to show as "overlay cards", simply are assigned the "CardSegue" that I've created, instead of having each and every presenting controller implement UIViewControllerTransitioningDelegate.
Problem
From one of the presenting controllers, I get a warning when dismissing the presented "Overlay card";
UIModalPresentationCustom presentation style can only be used with an animator or with unanimated dismissals.
I looked around, and all I could find was another post that seemed promising;
iOS 7.1 UIModalPresentationCustom warning message
But, the problem is that since my custom segue IS the transitionDelegate, trying to keep it as one logical unit, I can't really apply the reasoning of retaining the delegate...? I mean, the segue is running -- hence, the delegate is alive and well. I'm missing something, or there's an obvious reason that I cannot see right now for why the transitionDelegate MUST be separated from the custom segue?
My code
#define POPUP_MARGIN 25
#interface CardSegue () <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>
#property (nonatomic, assign, getter = isPresenting) BOOL presenting;
#end
#implementation CardSegue
- (void)perform
{
//Make sure that we are the delegate...
[self.destinationViewController setTransitioningDelegate:self];
[self.destinationViewController setModalPresentationStyle:UIModalPresentationCustom];
//Brute-force show the end-result!
[[self sourceViewController] presentViewController:[self destinationViewController] animated:YES completion:nil];
}
#pragma mark - UIViewControllerTransitioningDelegate Methods
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source
{
//Configure the animator
self.presenting = YES;
return self;
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.presenting = NO;
return self;
}
#pragma mark - UIViewControllerContextTransitioning Methods
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.5f;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
// Grab the from and to view controllers from the context
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
if (self.presenting)
{
// Set our ending frame. We'll modify this later if we have to
CGRect frame = fromViewController.view.frame;
CGRect endFrame = CGRectMake(POPUP_MARGIN, POPUP_MARGIN, frame.size.width - 2 * POPUP_MARGIN, frame.size.height - 2 * POPUP_MARGIN);
fromViewController.view.userInteractionEnabled = NO;
toViewController.view.alpha = 0.0f;
toViewController.view.layer.cornerRadius = 15;
//toViewController.view.layer.borderWidth = 1.5f;
toViewController.view.layer.masksToBounds = YES;
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
mainView.backgroundColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
[transitionContext.containerView addSubview:fromViewController.view];
[transitionContext.containerView addSubview:mainView];
[transitionContext.containerView addSubview:toViewController.view];
CGRect startFrame = endFrame;
startFrame.origin.y -= frame.size.height;
toViewController.view.frame = startFrame;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
mainView.backgroundColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
toViewController.view.frame = endFrame;
toViewController.view.alpha = 1.0f;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
else {
// Set our ending frame. We'll modify this later if we have to
CGRect frame = toViewController.view.frame;
CGRect endFrame = CGRectMake(POPUP_MARGIN, POPUP_MARGIN, frame.size.width - 2 * POPUP_MARGIN, frame.size.height - 2 * POPUP_MARGIN);
toViewController.view.userInteractionEnabled = YES;
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
mainView.backgroundColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.5];
[transitionContext.containerView addSubview:toViewController.view];
[transitionContext.containerView addSubview:mainView];
[transitionContext.containerView addSubview:fromViewController.view];
endFrame.origin.y += frame.size.height;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
mainView.backgroundColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
fromViewController.view.frame = endFrame;
fromViewController.view.alpha = 0.0f;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}
#end
#pragma mark - iAd method.
/*Starts:iAd*/
-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
Class cls = NSClassFromString(#"ADBannerView");
if(cls!=nil)
{
[self layoutForCurrentOrientation:YES];
}
}
-(void)createADBannerView
{
NSString *contentSize = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? ADBannerContentSizeIdentifierPortrait : ADBannerContentSizeIdentifierPortrait;
CGRect frame;
frame.size = [ADBannerView sizeFromBannerContentSizeIdentifier:contentSize];
frame.origin = CGPointMake(0.0, CGRectGetMaxY(self.view.bounds));
// Now to create and configure the banner view
ADBannerView *bannerView = [[ADBannerView alloc] initWithFrame:frame];
// Set the delegate to self, so that we are notified of ad responses.
bannerView.delegate = self;
// Set the autoresizing mask so that the banner is pinned to the bottom
bannerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin;
bannerView.requiredContentSizeIdentifiers = [NSSet setWithObjects:ADBannerContentSizeIdentifierPortrait, ADBannerContentSizeIdentifierPortrait, nil];
// At this point the ad banner is now be visible and looking for an ad.
[self.view addSubview:bannerView];
self.banner = bannerView;
[bannerView release];
}
-(void)layoutForCurrentOrientation:(BOOL)animated
{
CGFloat animationDuration = animated ? 0.2 : 0.0;
// by default content consumes the entire view area
CGRect contentFrame = self.view.bounds;
CGPoint bannerOrigin = CGPointMake(CGRectGetMinX(contentFrame), CGRectGetMaxY(contentFrame));
CGFloat bannerHeight = 0.0;
banner.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
bannerHeight = 55.0;
if(banner.bannerLoaded)
{
contentFrame.size.height -= bannerHeight;
bannerOrigin.y -= bannerHeight;
}
else
{
bannerOrigin.y += bannerHeight;
}
// And finally animate the changes, running layout for the content view if required.
NSLog(#"[UIApplication sharedApplication].statusBarOrientation = %d",[UIApplication sharedApplication].statusBarOrientation);
[UIView animateWithDuration:animationDuration
animations:^{
contentView.frame = contentFrame;
[contentView layoutIfNeeded];
banner.frame = CGRectMake(0,361, banner.frame.size.width, banner.frame.size.height);
}];
}
/*Ends:iAd*/
/*Starts:Added By:CP.Date:26-Dec-2010.
AdMob methods*/
#pragma mark - AdMobDelegate methods
-(NSString *) publisherIdForAd:(AdMobView *)adView
{
return #"a14f91029b8c719"; // this should be prefilled; if not, get it from www.admob.com
}
-(UIViewController *) currentViewControllerForAd:(AdMobView *)adView
{
return self;
}
-(UIColor *)adBackgroundColorForAd:(AdMobView *)adView
{
return [UIColor colorWithRed:0 green:0 blue:0 alpha:1]; // this should be prefilled; if not, provide a UIColor
}
-(UIColor *)primaryTextColorForAd:(AdMobView *)adView
{
return [UIColor colorWithRed:1 green:1 blue:1 alpha:1]; // this should be prefilled; if not, provide a UIColor
}
-(UIColor *)secondaryTextColorForAd:(AdMobView *)adView
{
return [UIColor colorWithRed:1 green:1 blue:1 alpha:1]; // this should be prefilled; if not, provide a UIColor
}
-(void) didReceiveAd:(AdMobView *)adView
{
adMobAd.frame = CGRectMake(0,361,320,55);
//adMobAd = [AdMobView requestAdOfSize:ADMOB_SIZE_748x110 withDelegate:self];
[self.view addSubview:adMobAd];
}
// Sent when an ad request failed to load an ad
-(void)didFailToReceiveAd:(AdMobView *)adView
{
Class cls = NSClassFromString(#"ADBannerView");
if(cls!=nil)
{
if(banner == nil)
{
[self createADBannerView];
}
[self layoutForCurrentOrientation:NO];
}
[adMobAd removeFromSuperview]; // Not necessary since never added to a view, but doesn't hurt and is good practice
[adMobAd release];
adMobAd = nil;
// we could start a new ad request here, but in the interests of the user's battery life, let's not
}
/*Ends:Added By:CP.Date:26-Dec-2010.
AdMob methods*/
first of all be clear about iad or admob , that are two different plateform for displaing adv in your app.
i think you are try to integrate admob adv. you need to following steps for it.
http://www.edumobile.org/iphone/iphone-programming-tutorials/how-to-admob-integrate-in-your-application-in-iphone/
I am switching and scaling properly iAd on portraid and landscape mode excepts when view starts from landscape mode. In this case, iAd remains at narrow width that corresponds to portraid. Then when rotate the device to portraid and back to landscape, is solved. How to solve it? Thank you.
- (void)viewDidLoad
{
//iAd
adView =[[ADBannerView alloc] initWithFrame:CGRectZero];
adView.requiredContentSizeIdentifiers = [NSSet setWithObjects: ADBannerContentSizeIdentifierPortrait, ADBannerContentSizeIdentifierLandscape, nil];
adView.delegate = self;
[self.view addSubview:adView];
[super viewDidLoad];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration {
if (UIInterfaceOrientationIsPortrait(orientation)) {
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
}
You do not tell the adView with which orientation to start, so it starts with the default orientation.
Try adding the following in viewDidLoad:
if (UIInterfaceOrientationIsPortrait([UIDevice currentDevice].orientation)) {
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
[self.view addSubview:adView];
I have this lovely nav bar asset:
navBar view http://dl.dropbox.com/u/1734050/ViewWithNavBar.jpg
and when users tap on the middle button (one with the arrows) it will bring up this other lovely "share box" asset
shareBox dropdown from navBar http://dl.dropbox.com/u/1734050/navBarWithShareBox.jpg
What I have in the code so far is that when the screen is tapped, the nav bar will appear, and disappear on another tap. Secondly, when the user taps on the "share" button, the share box comes up, and the user can tap outside of the box to dismiss it.
Here is the problem: I cannot dismiss the nav bar after bringing up the share box!
Here is some code:
-(void)viewDidLoad {
...
...
...
UITapGestureRecognizer *tapNavBar = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapForNavBar:)];
self.tapForNavBar = tapNavBar;
[self.viewForTaps addGestureRecognizer:self.tapForNavBar];
// btw, tapForNavBar is a UITapGestureRecognizer instance variable.
// also, viewForTaps is a view (instance variable) I made to handle
// where the user could tap (most of the screen)
}
#pragma mark -
#pragma mark Tap and Gesture Methods
-(void)handleTapForNavBar:(UIGestureRecognizer *)gestureRecognizer {
if (self.navBarIsHidden) {
[UIView animateWithDuration:0.5 animations:^ {
//self.primeViewController.view.alpha = 0.8;
self.navBar.alpha = 1.0;
}];
self.detailViewButton.userInteractionEnabled = YES;
self.shareButton.userInteractionEnabled = YES;
self.aboutAppButton.userInteractionEnabled = YES;
self.navBarIsHidden = NO;
}
else {
[UIView animateWithDuration:0.5 animations:^ {
self.navBar.alpha = 0.0;
//self.primeViewController.view.alpha = 1.0;
}];
self.detailViewButton.userInteractionEnabled = NO;
self.shareButton.userInteractionEnabled = NO;
self.aboutAppButton.userInteractionEnabled = NO;
self.navBarIsHidden = YES;
}
}
Ok, so that should look all dandy (and works like it too!) -- now here is perhaps where it gets unorthodox?
-(IBAction)showShareMenu:(id)sender {
if (self.navBarShareBoxIsHidden) {
[UIView animateWithDuration:0.5 animations:^ {
self.navBarShareBox.alpha = 1.0;
}];
[self.tapForNavBar removeTarget:nil action:NULL];
UITapGestureRecognizer *tapShareBox = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapForShareBox:)];
self.tapForShareBox = tapShareBox;
[self.viewForTaps addGestureRecognizer:self.tapForShareBox];
self.navBarShareBoxIsHidden = NO;
self.twitterButton.userInteractionEnabled = YES;
self.facebookButton.userInteractionEnabled = YES;
self.googlePlusButton.userInteractionEnabled = YES;
}
else {
[UIView animateWithDuration:0.5 animations:^ {
self.navBarShareBox.alpha = 0.0;
}];
[self.tapForShareBox removeTarget:nil action:NULL];
[self.tapForNavBar addTarget:self action:#selector(handleTapForNavBar:)];
self.navBarShareBoxIsHidden = YES;
self.twitterButton.userInteractionEnabled = NO;
self.facebookButton.userInteractionEnabled = NO;
self.googlePlusButton.userInteractionEnabled = NO;
}
}
I then create this method to handle the specific shareBox tapping:
-(void)handleTapForShareBox:(UIGestureRecognizer *)gestureRecognizer {
if (!self.navBarShareBoxIsHidden) {
[UIView animateWithDuration:0.5 animations:^ {
self.navBarShareBox.alpha = 0.0;
}];
self.navBarShareBoxIsHidden = YES;
self.twitterButton.userInteractionEnabled = NO;
self.facebookButton.userInteractionEnabled = NO;
self.googlePlusButton.userInteractionEnabled = NO;
[self.tapForShareBox removeTarget:nil action:NULL];
[self.tapForNavBar addTarget:self action:#selector(handleTapForNavBar:)];
}
}
I'm assuming my problem is coming from alloc/initing the new UITapGestureRecognizer in the -(IBAction)showShareMenu method. I thought by using the removeTarget... and addTarget messages I could easily tell my code which TapGesture method it should use, but considering it isn't working, I was wrong! Where did I go wrong? If you need more info, I'd be happy to give more.
Ah Ha! Looks like I found a solution! In my handleTapForShareBox method I did this:
-(void)handleTapForShareBox:(UIGestureRecognizer *)gestureRecognizer {
if (!self.navBarShareBoxIsHidden) {
[UIView animateWithDuration:0.5 animations:^ {
self.navBarShareBox.alpha = 0.0;
}];
self.navBarShareBoxIsHidden = YES;
self.twitterButton.userInteractionEnabled = NO;
self.facebookButton.userInteractionEnabled = NO;
self.googlePlusButton.userInteractionEnabled = NO;
[self.tapForShareBox removeTarget:nil action:NULL];
//[self.tapForNavBar addTarget:self action:#selector(handleTapForNavBar:)];
// Here is the new stuff, I added another alloc init of a UITapGestureRecognizer
// and re-assigned it to my UITap instance variable
UITapGestureRecognizer *tapNavBar = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapForNavBar:)];
self.tapForNavBar = tapNavBar;
[self.viewForTaps addGestureRecognizer:self.tapForNavBar];
}
}
It works great now! However, there were a couple things:
1) Do I have to release the UITapGestureRecognizer local pointer I created? Or because I initWithTarget it will be autoreleased?
2) Is this a hack? Or is this a proper way of passing different tap methods around? I'm just a little confused why the removeTarget and addTarget didn't do the trick.