Andy Andy - 2 months ago 25
iOS Question

Resolve conflict between two pan gesture recognizers

I have the following hierarchy:


  • View

    • Subview




Each of those views has
UIPanGestureRecognizer
assigned. Outer pan gesture recognizer is only interested in vertical panning, so I have the delegate method implemented for that:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint velocity = [panGestureRecognizer velocityInView:panGestureRecognizer.view];
return fabs(velocity.y) > fabs(velocity.x);
}


However Subview's pan gesture always takes precedence in recognition. Is there any way to make outer pan gesture recognizer to recognize first and then if it fails, pan gesture from subview can take over?

I tried simultaneous recognition and it works, but then both recognizers start panning:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer

shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}

Answer

Since iOS 7, UIGestureRecognizerDelegate Protocol has already declared two delegate methods for your need, you can either use |gestureRecognizer:shouldRequireFailureOfGestureRecognizer:| or |gestureRecognizerShouldBegin:shouldBeRequiredToFailByGestureRecognizer:| but in the opposite way.

The following snippet is my UIPanGestureRecognizer delegate implementation:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
    CGPoint velocity = [panGestureRecognizer velocityInView:panGestureRecognizer.view];
    return fabs(velocity.y) > fabs(velocity.x);
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    if (otherGestureRecognizer == panGestureOfSubView) {
        return YES;
    }

    return NO;
}