Gestor de reconocimiento y acciones de botón

Tengo una jerarquía de vista que se ve así:

UIView (A) UIView > UIImageView UIView > UIView (B) UIView > UIView (B) > Rounded Rect Button UIView > UIView (B) > UIImageView UIView > UIView (B) > UILabel 

He adjuntado reconocedor (es) de gestos a mi UIView (B). El problema que estoy enfrentando es que no obtengo ninguna acción para el Botón de Rectángulo Redondeado que está dentro de UIView (B). El reconocedor de gestos SingleTap captura / anula el evento Touch Up Inside del botón.

¿Cómo puedo hacer que funcione? ¡Pensé que la jerarquía de la cadena de respuesta se aseguraría de que al evento de toque de botón se le dé preferencia, y se activará! ¿Qué me estoy perdiendo?

Aquí hay un código relacionado:

 #pragma mark - #pragma mark View lifecycle (Gesture recognizer setup) - (void)viewDidLoad { [super viewDidLoad]; // double tap gesture recognizer UITapGestureRecognizer *dtapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizer:)]; dtapGestureRecognize.delegate = self; dtapGestureRecognize.numberOfTapsRequired = 2; [self.viewB addGestureRecognizer:dtapGestureRecognize]; // single tap gesture recognizer UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureRecognizer:)]; tapGestureRecognize.delegate = self; tapGestureRecognize.numberOfTapsRequired = 1; [tapGestureRecognize requireGestureRecognizerToFail:dtapGestureRecognize]; [self.viewB addGestureRecognizer:tapGestureRecognize]; // add gesture recodgnizer to the grid view to start the edit mode UILongPressGestureRecognizer *pahGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerStateChanged:)]; pahGestureRecognizer.delegate = self; pahGestureRecognizer.minimumPressDuration = 0.5; [self.viewB addGestureRecognizer:pahGestureRecognizer]; [dtapGestureRecognize release]; [tapGestureRecognize release]; [pahGestureRecognizer release]; } #pragma mark - #pragma mark Button actions - (IBAction)buttonTouchUpInside:(id)sender { NSLog(@"%s, %@", __FUNCTION__, sender); } #pragma mark - #pragma mark Gesture recognizer actions - (void)singleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { NSLog(@"%s", __FUNCTION__); } - (void)doubleTapGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer { NSLog(@"%s", __FUNCTION__); } - (void)longPressGestureRecognizerStateChanged:(UIGestureRecognizer *)gestureRecognizer { switch (gestureRecognizer.state) { case UIGestureRecognizerStateEnded: { NSLog(@"%s", __FUNCTION__); break; } default: break; } } 

En el método “shouldReceiveTouch”, debe agregar una condición que devolverá NO si el toque está en el botón.

Esto es del ejemplo Apple SimpleGestureRecognizers .

 - (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; } 

espero que ayude

Editar

Como Daniel señaló, debe cumplir con UIGestureRecognizerDelegate para que funcione.

shani

También tuve el mismo problema, luego probé con

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{ if ([touch.view isKindOfClass:[UIButton class]]) { //change it to your condition return NO; } return YES; } 

Está funcionando perfectamente ahora ………

En general, utilizamos el método de delegado siguiente para evitar el toque en todo tipo de UIControls:

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

Nota: NO haga esta comprobación (compruebe el tipo de clase recognizer.view) el gestureRecognizerShouldBegin, no funcionará.

Aquí hay una versión de Swift 3.0 :

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

No te olvides de:

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

Aquí hay una versión de Swift:

 func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if (touch.view!.isKindOfClass(UIButton)) { return false } return true } 

No te olvides de:

  1. Haga que su clase se ajuste a UIGestureRecognizerDelegate
  2. Haga que su objeto tapper se delegue en sí mismo (p. Ej .: tapper.delegate = self )

La mejor solución es, en mi opinión, usar el siguiente fragmento de código:

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