How to block a gesture from superview to subview?

You have to implement the UIGestureRecognizerDelegate method:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

And add your controller as the delegate of the gesture recognizers. Then, when two gesture recognizers respond to a gesture, this method will be called and here you can implement the logic you want for your app.

In the interface declaration of the controller you have to type:

@interface testcViewController () <UIGestureRecognizerDelegate>

Then, when creating the gesture recognizer:

UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];
swipe.direction = UISwipeGestureRecognizerDirectionDown;
swipe.delegate = self;
[self.view addGestureRecognizer:swipe];

And then, finally, you add this method to the controller:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    BOOL shouldInteract = NO;
    //Here you decide whether or not the two recognizers whould interact.
    return shouldInteract;
}

EDIT You can also implement

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;

And here, detect if you have already presented the subviews, and block any gesture you want.


set userinteractionEnabled to NO of your subView

 subview.userinteractionEnabled=NO

if you dont want to disable userInteraction then use cancelsTouchesInView method

cancelsTouchesInView—If a gesture recognizer recognizes its gesture, it unbinds the remaining touches of that gesture from their view (so the window won’t deliver them). The window cancels the previously delivered touches with a (touchesCancelled:withEvent:) message. If a gesture recognizer doesn’t recognize its gesture, the view receives all touches in the multi-touch sequence.


To block all gesture recognizers from superviews I created a UIGestureRecognizer sub class that will do just that when attached to a view. See the following code (taken from my WEPopover project):

#import "WEBlockingGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>

@implementation WEBlockingGestureRecognizer

- (id)init {
    return [self initWithTarget:self action:@selector(__dummyAction)];
}

- (id)initWithTarget:(id)target action:(SEL)action {
    if ((self = [super initWithTarget:target action:action])) {
        self.cancelsTouchesInView = NO;
    }
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    if (self.state == UIGestureRecognizerStatePossible) {
        self.state = UIGestureRecognizerStateBegan;
    }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    self.state = UIGestureRecognizerStateRecognized;
}

- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer {
    return [self isGestureRecognizerAllowed:preventingGestureRecognizer];
}

- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer {
    return ![self isGestureRecognizerAllowed:preventedGestureRecognizer];
}

- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return ![self isGestureRecognizerAllowed:otherGestureRecognizer];
}

- (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return NO;
}

- (BOOL)isGestureRecognizerAllowed:(UIGestureRecognizer *)gr {
    return [gr.view isDescendantOfView:self.view];
}

- (void)__dummyAction {

}

@end

If you want to block all gesture recognizers attached to parent views of some view, just do the following:

- (void)blockParentGesturesForView:(UIView *)v {
    [v addGestureRecognizer:[WEBlockingGestureRecognizer new]];
}