Search code examples
iosobjective-ctouchuigesturerecognizer

How to cancel button tap if UIGestureRecognizer fires?


Update: The problem seems to be the dependency on another GestureRecognizer to fail. See comments and test project below this question!

In my iPhone app I have a view with multiple UIButtons as subviews. The view also has a UITapGestureRecognizer which is listening for taps with two fingers.

When a two-finger-tap occurs on the view I don't want the buttons to react to the tap, even if one of the fingers was inside the button. I thought this is what "cancelsTouchesInView" is for, but that doesn't work.

My question now is: How to tell my buttons to ignore taps when a gesture is recognized?

Edit: This is my gesture recognizer.

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapped:)];
[doubleTap setNumberOfTouchesRequired:2];
[doubleTap setNumberOfTapsRequired:1];
[doubleTap setCancelsTouchesInView:YES];
[doubleTap setDelaysTouchesBegan:YES];
[doubleTap setDelaysTouchesEnded:YES];
[self.view addGestureRecognizer:doubleTap];
[doubleTap release];

Solution

  • According to an Apple dev this is a bug. I filed a bug report with Apple. Thanks a lot for your hints, Deepak and gcamp!

    Bug report:

    Summary: When adding two UITapGestureRecognizers to a view where one requires the other to fail (requiresGestureRecognizerToFail:) the cancelsTouchesInView property of the first gesture recognizer is ignored.

    Steps to Reproduce: 1. Create two UITapGestureRecognizers (r1 and r2) 2. Configure r1 to require two touches and one tap and to delay touchesBegan 3. Configure r2 to require two touches and two taps and to delay touchesBegan 4. Configure r1 to require r2 to fail [r1 requiresGestureRecognizerToFail:r2] 5. Add r1 and r2 to a view 6. Place a UIButton in the view 7. Tap with two fingers on the view, one should hit the button.

    Expected Results: r1 should be recognized and the button tap should be canceled (cancelsTouchesInView defaults to YES for UITapGestureRecognizers).

    Actual Results: r1 is recognized but the button touchedUpInside event is fired, too.

    Regression: cancelTouchesInView works fine for r1 once you remove the dependency on r2 (step 4).