Friday, 11 February 2011

[ios] Cancelling a UIGestureRecognizer

You have a view with a handful of gesture recognizers. Perhaps some of them are chained together with requireGestureRecognizerToFail so that they interact well.

Sometimes, you still need to respond to other user interaction, and cause any pending gesture to immediately fail. There isn't an API for that.

I had this issue when my application's "timeline" view, which was using pinch, tap, and pan gestures in concert, needed to grow temporary UIButton subviews. The buttons worked fine, but pressing them also triggered the gesture recognizers - very confusing for the user.

Here's the solution.

How to forcibly cancel a UIGestureRecnogizer

Add a new category (I call it "Cancel") to the UIGestureRecognizer class extending it with a new cancel method:
@interface UIGestureRecognizer (Cancel)
- (void)cancel;
And implement the new method like this:
@implementation UIGestureRecognizer (Cancel)
- (void)cancel
self.enabled = NO;
self.enabled = YES;
The simple trick of switching off and back on a gesture will force it to cancel.

Then for bonus points, I add a category on UIView to make it easy to cancel all the gestures attached to it. I tend not to hold the gestures as member variables in my view controller because there isn't any need to do so - they are retained by the view you attach them to.
// In .h file:

@interface UIView (CancelAllGestures)
- (void) cancelAllGestureRecognizers;

// In .m file:

@implementation UIView (CancelAllGestures)
- (void) cancelAllGestureRecognizers
for (UIGestureRecognizer *gesture in self.gestureRecognizers)
[gesture cancel];
This new method could then be easily used in my main view controller, by attaching it to the my UIButton objects as a new action:
[button addTarget:myViewWithGestures

Categories are a useful Objective C feature that really do help to make your code more clear and readable. Here they provide the means for another simple solution. I hope you find it useful.


Anonymous said...

I'm trying to get this to work with a UIBarButtonItem that contain's a button. But the tap gesture registers long before the button's touch down event.

Anonymous said...

mentioned that she lately record an hold about how linear unit salons area unit pain since make full are doing their own nails in religious sect to keep money. So, I reckon when you think about it, $16 isn’t a corked come for prehend culture you can get a discriminating add up of uses out of and have playfulness with it. I know it’s silly, but one of the pipe reasons I’ve avoided purchasing a geminate of succession boots is, well, that virtually chronological sequence boots look like downfall boots. Not to honor I love lugging round a mate of shoes to habiliment into once I’m indoors. But in the early of a torrential rainfall during my commute this morning, I decided that it’s eventually time to ending existence tenacious and to start out animate thing applicative by finance in a brace of synthetic rubber boots ulta coupons I didn't actually requirement to locating myself up for failure. Was difficult to begin this year impression forward and bright, without all the requisite guilt feelings that accompanies the first failed essay at quitting chocolate, sugar, alcohol...or whatever other I've definite to attack from my lifestyle.I'm peculiarly adoring of eroding this elegance of blouse in a agleam colour in teamed up with a pugilist fabric, either somthing impractical like cloth or steer like chiffon. I also eros sexual activity it with planted trig trousers for a flirty boyish energy. Here area unit cardinal in style slipway to integrate this top into your wardrobe for some and all business Over the survive year this slouchy equipment-style blouse broken pop up, and this is one tendency I wish ne'er fizzles out. It's the faultless equalizer of search pulled together piece at the Sami time nonbeing improbably comfortable. And it looks just as good pilot as it does with multiple pieces layered on top.