UITapGestureRecognizer conflicting with CCButton - ios

I've looked around on Stack for solutions to this and found quite a few results, but I'm still unable to fix my problem, mainly because I'm working on a CCNode opposed to some UIView.
Anyways, my CCButton works find without the UITapGestureRecognizer, but when I implement it, it overrides my button press. Obviously I would like to avoid this.
My code is below. My swipe gestures work perfectly, but the tap interferes with my button. I'm not sure if I'm adding the gesture recognizer to the wrong view, because - (BOOL)gesturerecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch never runs, which is where I would put in my exception. If anyone can give me some code/ideas on how to fix this it would be greatly appreciated, thanks!
-(void)didLoadFromCCB
UITapGestureRecognizer * gridTapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(gridTapped)];
[[[CCDirector sharedDirector] view] addGestureRecognizer:gridTapped];
//this works totally fine
UISwipeGestureRecognizer * swipeLeft= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeLeft)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[[[CCDirector sharedDirector] view] addGestureRecognizer:swipeLeft];
}
-(void)gridTapped {
//this works!
CCLOG(#"Grid tapped");
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
//This never runs
CCLOG(#"gesture recognized");
if ((touch.view == mainMenuButton)) {
return NO;
}
return YES;
}

Try setting the UITapGestureRecognizer delegate:
gridTapped.delegate = self;
You'll need to declare the VC class as implementing <UITapGestureRecognizerDelegate>

Related

MultipleGesture on same view

I am adding two gesture on a view. One is tap gesture and second is swipe gesture. Whenever user tries to swipe the view , tap gesture method gets called (tap gesture gets detected). What could be the reason ? Tap gesture should get ignore in this case.
below is the code .
UISwipeGestureRecognizer *swipeGest = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(itemSwiped:)];
swipeGest.direction = UISwipeGestureRecognizerDirectionUp ;
[messageView addGestureRecognizer:swipeGest];
UITapGestureRecognizer *gest = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(itemSelected:)];
[messageView addGestureRecognizer:gest];
use this delegate method to avoid other gesture
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
[otherGestureRecognizer requireGestureRecognizerToFail:gestureRecognizer];
return false;
}else if([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]]){
[otherGestureRecognizer requireGestureRecognizerToFail:gestureRecognizer];
return false;
}
return true;
}
Because your using multiple gesture on same view. this may over hide one another property .For Ex: first gesture recognizer recognizes the gesture (tap in this case) it cancels all touch events. Therefore the remaining gesture recognizers will never finish recognition, and will never fire their events.
In order to add more than one UIGestureRecognizer onto the same view, you need to set the delegate property (UIGestureRecognizerDelegate)
yourGesture.delegate = self
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if (gestureRecognizer isKindOfClass: [UISwipeGestureRecognizer class] || gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]) {
return YES
} else {
return NO
}
}
Try this;
UISwipeGestureRecognizer *swipeGest = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(itemSwiped:)];
swipeGest.direction = UISwipeGestureRecognizerDirectionUp ;
[messageView addGestureRecognizer:swipeGest];
UITapGestureRecognizer *gest = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(itemSelected:)];
gest.numberOfTapsRequired = 1;
[messageView addGestureRecognizer:gest];
-(void)itemSwiped:(UISwipeGestureRecognizer*)gesture
{
NSLog(#"swipe");
}
-(void)itemSelected:(UITapGestureRecognizer*)gesture
{
NSLog(#"tap");
}
Change single tap to doubletap gesture. so you can be sure user only double tap or swipe. It is good advice from me please follow it.

Conflicting UIPanGestureRecognizer (3 fingers) and UIPinchGestureRecognizer

I'm adding both a UIPanGestureRecognizer and UIPinchGestureRecognizer to the same view. This typically would not cause any issues, but the requirement for 3 fingers with my UIPanGestureRecognizer is causing problems:
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(pinched:)];
[self.view addGestureRecognizer:pinchGesture];
UIPanGestureRecognizer panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panning:)];
panGesture.minimumNumberOfTouches = 3;
panGesture.maximumNumberOfTouches = 3;
[self.view addGestureRecognizer:panGesture];
Occasionally, the pinch gesture will get called when the pan should have been. It works ~50% of the time, but what is a better way to implement these two gestures on the same view so the accuracy is better?
Edit: I only want one gesture to happen at a time.
Set the delegates for the gestures to self and set your ViewController to implement UIGestureRecognizerDelegate
And add this method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
other post has a typo I think, but use this
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return NO;
}
and add this so other gestures will fail before the gesture you want to start
requireGestureRecognizerToFail

How to detect of tap gesture is from uiwebview or self.view?

Hello everyone I have a uitapgesture on my view using the following code :
UITapGestureRecognizer *tap= [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(TAPGestureRecognizer)];
tap.numberOfTapsRequired=1;
tap.delegate = self;
[self.view addGestureRecognizer:tap];
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
And I have a uiwebview as a subview in my UIview. The problem is that on the uivewview HTML it had a onclick(); which in turn is calling the tapgesture. Any help?
FirstView.image=[UIImage imageNamed:#"shape1.jpg"];
FirstView.tag=1;
FirstView.userInteractionEnabled=YES;
[FirstView addGestureRecognizer:[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(firstimagetouch:)]];
SecondWebView.tag=2;
SecondWebView.userInteractionEnabled=YES;
[SecondWebView addGestureRecognizer:[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(firstimagetouch:)]];
-(void)firstimagetouch:(UIGestureRecognizer *)sender
{
UIView * view=sender.view;
NSLog(#"%ld",(long)view.tag);
}
try like this first add gesture recognizer to view and then your webview according to give him tag value and get tag value. and do what you want.

UITableView swipe gesture requires near perfect accuracy

I'm working on a custom swipe event for a UITableView that uses custom UITableViewCell subclass. I included the UIGestureRecognizerDelegate in my header, and have this in viewDidLoad:
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(didSwipe:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft.numberOfTouchesRequired = 1;
[self.tableView addGestureRecognizer:swipeLeft];
My swipeLeft method looks like so:
-(void)didSwipe:(UISwipeGestureRecognizer *)recognizer {
if (recognizer.state == UIGestureRecognizerStateEnded)
{
CGPoint swipeLocation = [recognizer locationInView:self.tableView];
NSIndexPath *swipedIndexPath = [self.tableView indexPathForRowAtPoint:swipeLocation];
NSDictionary *clip = [self.clips objectAtIndex:swipedIndexPath.row];
NSLog(#"Swiped!");
}
}
It's sort of working, but the swipe has to be incredibly precise. Like nearly impossibly precise.
I almost got it working by using a UIPanGestureRecognizer instead, but unfortunately it didn't play nice with the global side drawer component that uses a global pan gesture recognizer (ECSlidingViewController for those interested).
Is there any way around this? Any help would be appreciated, as I've been googling around and browsing SO for hours looking for a solution.
As pointed out by Kolin Krewinkel on Twitter, implementing these 2 delegate methods did the trick:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
return YES;
}
I was having a similar problem using the ECSlidingViewController and swipe-to-delete on a UITableView (the top view controller in my case slides to the left to reveal the menu).
I fixed the problem by adding a delegate to the default panGesture property of my ECSlidingViewController like this to only pull in the menu if the swipe starts in the very right-hand edge of the screen:
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([gestureRecognizer locationInView:gestureRecognizer.view].x > ([UIScreen mainScreen].bounds.size.width - 60.0))
{
return YES;
}
return NO;
}

iOS6 bug in UITapGestureRecognizer gestureRecognizer:shouldReceiveTouch:?

The following code in my view controller results in an EXC_BAD_ACCESS at the touch.view call:
- (BOOL)handleSingleTap:(UITapGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIControl class]]) { // <<<< EXC_BAD_ACCESS HERE
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
[self.view endEditing:YES]; // dismiss the keyboard
return YES; // handle the touch
}
touch appears to be a zombie. Specifically, touch is set to an address, and the debugger thinks that's a UITouch pointer, but it doesn't have any properties:
This did not happen in iOS 4.x. So iOS 6 bug or my fault?
The gesture recognizer is set up as follows (in the ViewController):
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:shouldReceiveTouch:)];
[tapRecognizer setDelegate:self];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setNumberOfTouchesRequired:1];
tapRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapRecognizer];
[tapRecognizer release];
UPDATE/SOLUTION:
Thanks to Rob for pointing out the user error on my part. Not only that, but I don't actually need the TapRecognizer since I just want to know a touch happened.
Here's the correct code to dismiss the on-screen keyboard with a touch anywhere but in a UIControl:
In the ViewController's viewDidLoad:
UIGestureRecognizer *myRecognizer = [[UIGestureRecognizer alloc] init];
[myRecognizer setDelegate:self];
myRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:myRecognizer];
[myRecognizer release];
And:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIControl class]]) {
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
[self.view endEditing:YES]; // dismiss the keyboard
return YES; // handle the touch
}
You're using a method, handleSingleTap:shouldReceiveTouch:, whose signature does not conform to the permissible signatures. See the Overview section of UIGestureRecognizer Class Reference. It should only have the one parameter, the gesture recognizer.
I think you may be confusing the handler with the UIGestureRecognizerDelegate protocol method gestureRecognizer:shouldReceiveTouch:.

Resources