UIButton inside a view that has a UITapGestureRecognizer
You can set your controller or view (whichever creates the gesture recognizer) as the delegate of the UITapGestureRecognizer
. Then in the delegate you can implement -gestureRecognizer:shouldReceiveTouch:
. In your implementation you can test if the touch belongs to your new subview, and if it does, instruct the gesture recognizer to ignore it. Something like the following:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// test if our control subview is on-screen
if (self.controlSubview.superview != nil) {
if ([touch.view isDescendantOfView:self.controlSubview]) {
// we touched our control surface
return NO; // ignore the touch
}
}
return YES; // handle the touch
}
As a follow up to Casey's follow up to Kevin Ballard's answer:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIControl class]]) {
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
return YES; // handle the touch
}
This basically makes all user input types of controls like buttons, sliders, etc. work
Found this answer here: link
You can also use
tapRecognizer.cancelsTouchesInView = NO;
Which prevents the tap recognizer to be the only one to catch all the taps
UPDATE - Michael mentioned the link to the documentation describing this property: cancelsTouchesInView
As a follow up to Kevin Ballard's answer, I had this same problem and ended up using this code:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIButton class]]){
return NO;
}
return YES;
}
It has the same effect but this will work on any UIButton at any view depth (my UIButton was several views deep and the UIGestureRecognizer's delegate didn't have a reference to it.)
In iOS 6.0 and later, default control actions prevent overlapping gesture recognizer behavior. For example, the default action for a button is a single tap. If you have a single tap gesture recognizer attached to a button’s parent view, and the user taps the button, then the button’s action method receives the touch event instead of the gesture recognizer. This applies only to gesture recognition that overlaps the default action for a control, which includes:.....
From Apple's API doc