iAdSuite bug leaves white space when ad disappears - objective-c

I'm trying to incorporate the iAdSuite tab bar view implementation in my app and I'm seeing the same problem in the suite and my app. When the ad appears, my content's view is getting properly resized and the ad appears correctly. When the ad then disappears, it leaves behind white space where it was located. However, I've confirmed that my content view does get resized back to its original height and it gets drawn down to its original bounds. You just can't see the part where the ad was. I've made sure every view gets a layoutIfNeeded and just about everything else I can think of to no avail. Any thoughts?
Edit: I've figured out what the problem is. Apple's example apparently adds _bannerView to self.view every time showBannerView: is called but never removes the view. That still doesn't make complete sense since the banner view is being moved offscreen, but removing it does solve the white space problem. My solution is as follows, but if anyone has a more elegant way, let me know.
- (void)layoutAnimated:(BOOL)animated {
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
CGRect contentFrame = self.view.bounds;
contentFrame.origin = CGPointMake(0.0, 0.0);
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:^{
_contentView.frame = contentFrame;
[_contentView layoutIfNeeded];
_bannerView.frame = bannerFrame;
}
completion:^(BOOL finished) {
if (!_bannerView.bannerLoaded) {
[_bannerView removeFromSuperview];
_bannerView=nil;
}
}];
}
- (void)showBannerView:(ADBannerView *)bannerView animated:(BOOL)animated
{
_bannerView = bannerView;
if (![self.view.subviews containsObject:_bannerView])
[self.view addSubview:_bannerView];
[self layoutAnimated:animated];
}
- (void)hideBannerView:(ADBannerView *)bannerView animated:(BOOL)animated
{
[self layoutAnimated:animated];
}

I had the same problem. Removing the bannerview from the super view in the hideBannerView delegate method seems to have solved it.
- (void)hideBannerView:(ADBannerView *)bannerView animated:(BOOL)animated
{
[self layoutAnimated:animated];
[_bannerView removeFromSuperview];
_bannerView = nil;
}

Thanks for this question and answer, I was pulling hairs with this one.
I changed the damn code like this and now the hiding animation works. I wonder why apple publishes buggy sample code...
- (void)layoutAnimated:(BOOL)animated hide:(BOOL)hide
{
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
CGRect contentFrame = self.view.bounds;
CGRect bannerFrame = _bannerView.frame;
if (!hide) {
contentFrame.size.height -= _bannerView.frame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
} else {
contentFrame.size.height += _bannerView.frame.size.height;
bannerFrame.origin.y = contentFrame.size.height;
}
[UIView animateWithDuration:animated ? 0.25 : 0.0 animations:^{
_contentView.frame = contentFrame;
[_contentView layoutIfNeeded];
_bannerView.frame = bannerFrame;
} completion:^(BOOL finished) {
if (hide) {
[_bannerView removeFromSuperview];
_bannerView=nil;
}
}];
}
- (void)showBannerView:(ADBannerView *)bannerView animated:(BOOL)animated
{
_bannerView = bannerView;
[self.view addSubview:_bannerView];
[self layoutAnimated:animated hide:NO];
}
- (void)hideBannerView:(ADBannerView *)bannerView animated:(BOOL)animated
{
[self layoutAnimated:animated hide:YES];
}

Related

Hide UINavBar and UITabBar at the same time with animation

Edit: I awarded the bounty to john since he put a lot of effort into his answer, and would get it anyways, but there's still no working solution. I am still looking for an answer, if someone knows how to do this it'd be greatly appreciated.
I want to add a "maximize" button to my app that hides the navigation and tab bar. The navbar and tabbar should slide in/out smoothly, and the inner/content view should also expand and shrink at the same rate as the navbar and tabbar.
I used [self.navigationController setNavigationBarHidden: YES/NO animated: YES]; for the navbar and found this thread How to hide uitabbarcontroller for hiding the tabbar.
UITabBar class extension:
- (void) setTabBarHidden:(BOOL)hidden animated:(BOOL)animated {
CGRect screenRect = [[UIScreen mainScreen] bounds];
float screenHeight = screenRect.size.height;
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
screenHeight = screenRect.size.width;
}
if (!hidden) {
screenHeight -= self.tabBar.frame.size.height;
}
[UIView animateWithDuration: (animated ? UINavigationControllerHideShowBarDuration : 0) animations: ^{
for (UIView* each in self.view.subviews) {
if (each == self.tabBar) {
[each setFrame: CGRectMake(each.frame.origin.x, screenHeight, each.frame.size.width, each.frame.size.height)];
} else {
[each setFrame: CGRectMake(each.frame.origin.x, each.frame.origin.y, each.frame.size.width, screenHeight)];
}
}
} completion: ^(BOOL finished) {
NSLog(#"Animation finished %d", finished);
}];
}
The problem is when I use the two at the same time (hiding/showing the nav and tab bar), it's not clean. If the navbar comes first, anything anchored to the bottom jumps (see example below), and if the tabbar comes first, the top jumps.
Example: I position the UIButton in the bottom right and set its autoresizing mask
resizeButton.frame = CGRectMake(self.view.bounds.size.width - 50, self.view.bounds.size.height - 100, 32, 32); // hardcoded just for testing purposes
resizeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
But when the navbar and tabbar are minimized the UIButton jumps between the two states (doesn't slide along with the tab bar). However, if I change it to attach to the top right, it slides perfectly with the nav bar.
Does anyone know how to solve this?
Edit:
This is the closet and most elegant solution I have so far (just trying to get a working concept):
[UIView animateWithDuration: UINavigationControllerHideShowBarDuration animations: ^{
if (self.isMaximized) {
self.tabBarController.view.frame = CGRectMake(0, 20, screenRect.size.width, screenRect.size.height + 49 - 20);
[self.navigationController setNavigationBarHidden:YES animated:YES];
} else {
self.tabBarController.view.frame = CGRectMake(0, 20, screenRect.size.width, screenRect.size.height - 20);
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
} completion: ^(BOOL finished) {
NSLog(#"Frame done: %#", NSStringFromCGRect(self.view.frame));
return;
}];
On maximizing:
Slides the navbar up, and slides the tabbar down, at the same time
The top of the inner/content view slides up, and the bottom of this view jumps down
On minimizing:
Slides the navbar down, and slides the tabbar up, at the same time
The top of the inner/content view slides down properly, but the bottom jumps to the final value, leaving whitespace which is then covered by the sliding tabbar
If I rearange the order of the minimizing-animations (so the navbar animatino is called first), then the top in the inner/content view jumps
the solution i use should eliminate the jump problem you see.
this solution is derived from an Objective-C category found Carlos Oliva's github page, and while the copyright in that code is "all rights reserved", i wrote him and he provided permission for use.
my category code varies only slightly from his code. also, find below the category code the invocation code that i use in my app.
from UITabBarController+HideTabBar.m
// the self.view.frame.size.height can't be used directly in isTabBarHidden or
// in setTabBarHidden:animated: because the value may be the rect with a transform.
//
// further, an attempt to use CGSizeApplyAffineTransform() doesn't work because the
// value can produce a negative height.
// cf. http://lists.apple.com/archives/quartz-dev/2007/Aug/msg00047.html
//
// the crux is that CGRects are normalized, CGSizes are not.
- (BOOL)isTabBarHidden {
CGRect viewFrame = CGRectApplyAffineTransform(self.view.frame, self.view.transform);
CGRect tabBarFrame = self.tabBar.frame;
return tabBarFrame.origin.y >= viewFrame.size.height;
}
- (void)setTabBarHidden:(BOOL)hidden {
[self setTabBarHidden:hidden animated:NO];
}
- (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated {
BOOL isHidden = self.tabBarHidden;
if (hidden == isHidden)
return;
UIView* transitionView = [self.view.subviews objectAtIndex:0];
if (!transitionView)
{
#if DEBUG
NSLog(#"could not get the container view!");
#endif
return;
}
CGRect viewFrame = CGRectApplyAffineTransform(self.view.frame, self.view.transform);
CGRect tabBarFrame = self.tabBar.frame;
CGRect containerFrame = transitionView.frame;
tabBarFrame.origin.y = viewFrame.size.height - (hidden ? 0 : tabBarFrame.size.height);
containerFrame.size.height = viewFrame.size.height - (hidden ? 0 : tabBarFrame.size.height);
[UIView animateWithDuration:kAnimationDuration
animations:^{
self.tabBar.frame = tabBarFrame;
transitionView.frame = containerFrame;
}
];
}
from my ScrollableDetailImageViewController.m
- (void)setBarsHidden:(BOOL)hidden animated:(BOOL)animated
{
[self setTabBarHidden:hidden animated:animated];
[self setStatusBarHidden:hidden animated:animated];
// must be performed after hiding/showing of statusBar
[self.navigationController setNavigationBarHidden:hidden animated:animated];
}
- (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated
{
id parent = self.navigationController.parentViewController;
if ([parent respondsToSelector:#selector(isTabBarHidden)]
&& hidden != [parent isTabBarHidden]
&& [parent respondsToSelector:#selector(setTabBarHidden:animated:)])
[parent setTabBarHidden:hidden animated:animated];
}
Just try this code, If it is working. I have written this code a year before. But, still it works good for me.
I didn't used the block based animations. Because it was written when I am new to iOS. Just try and optimize yourself as you wanted.
- (void) hideTabBar:(UITabBarController *) tabbarcontroller {
[self.navigationController setNavigationBarHidden:YES animated:YES];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
for(UIView *view in tabbarcontroller.view.subviews)
{
if ([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 480, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 480)];
}
}else if([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 1024, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 1024)];
}
}
}
[UIView commitAnimations];
}
// Method shows the bottom and top bars
- (void) showTabBar:(UITabBarController *) tabbarcontroller {
[self.navigationController setNavigationBarHidden:NO animated:YES];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
for(UIView *view in tabbarcontroller.view.subviews)
{
if ([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 430, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 436)];
}
}else if([[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, 975, view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 980)];
}
}
}
[UIView commitAnimations];
}
Try this
you can hide tabbar contrller and navigation bar using animation like:-
-(IBAction)hide:(id)sender
{
[self hideShowBars];
}
- (void) hideShowBars
{
CGRect rect = self.navigationController.navigationBar.frame;
CGRect rect1 = self.tabBarController.tabBar.frame;
if(self.navigationController.navigationBar.isHidden)
{
[self.navigationController.navigationBar setHidden:NO];
rect.origin.y=self.view.frame.origin.y;
}
else
{
rect.origin.y=self.view.frame.origin.y-rect.size.height;
}
if(self.tabBarController.tabBar.isHidden)
{
[self.tabBarController.tabBar setHidden:NO];
rect1.origin.y=self.view.frame.size.height-rect1.size.height-rect1.size.height;
}
else
{
rect1.origin.y=self.view.frame.size.height;
}
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.50];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(hideShowBarsAnimationStopped)];
self.navigationController.navigationBar.frame=rect;
self.tabBarController.tabBar.frame = rect1;
[UIView commitAnimations];
}
- (void) hideShowBarsAnimationStopped
{
if(self.navigationController.navigationBar.frame.origin.y==self.view.frame.origin.y)
return;
if(!self.navigationController.navigationBar.isHidden)
{
[self.navigationController.navigationBar setHidden:YES];
}
if(!self.tabBarController.tabBar.isHidden)
{
[self.tabBarController.tabBar setHidden:YES];
}
}

iAd issue:--> Every time empty iAd banners is coming instead of AdMobView

#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/

iAd doesn't fit width when starts from landscape mode

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];

Why is my iAd banner not showing?

- (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.

Attempting to "turn on/off" different UITapGestureReconginzer methods

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.