In the "shouldReceiveTouch" method you should add a condition that will return NO if the touch is in the button.

This is from apple SimpleGestureRecognizers example.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

    // Disallow recognition of tap gestures in the segmented control.
    if ((touch.view == yourButton)) {//change it to your condition
        return NO;
    }
    return YES;
}

hope it will help

Edit

As Daniel noted you must conform to UIGestureRecognizerDelegate for it to work.

shani


I also had the same problem , then i tried with

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{

    if ([touch.view isKindOfClass:[UIButton class]]) {      //change it to your condition
        return NO;
    }
    return YES;
}

It is working now perfectly.........


Generally speaking, we use below delegate method to avoid the touch in all kinds of UIControls:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if (([touch.view isKindOfClass:[UIControl class]])) {
         return NO;
    }
    return YES;
}

Note: DO NOT do this check (check the recognizer.view class type) the gestureRecognizerShouldBegin, it won't work.


Here is a Swift 3.0 version:

extension UIViewController: UIGestureRecognizerDelegate {

public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    if touch.view is UIButton {
        return false
    }
    return true
}

Don't forget to:

Make your tapper object delegate to self (e.g: tapper.delegate = self)


The best solution is to my mind using code snippet below:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint touchLocation = [touch locationInView:self.view];
    return !CGRectContainsPoint(self.menuButton.frame, touchLocation);
}