Reconhecimento de gestos e ações de botão

Eu tenho uma hierarquia de visão que é algo como isto:

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

Eu prendi o (s) reconhecedor (es) de gesto ao meu UIView (B). O problema que estou enfrentando é que eu não recebo nenhuma ação pelo botão Rounded Rect que está dentro do UIView (B). O reconhecedor de gestos singleTap captura / substitui o evento Retocar interior do botão.

Como posso fazer isso funcionar? Eu pensei que a hierarquia da cadeia responderá para que o evento de toque no botão tenha preferência, e ele será acionado! O que estou perdendo?

Aqui está um 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; } } 

    No método “shouldReceiveTouch” você deve adicionar uma condição que retornará NO se o toque estiver no botão.

    Isto é do exemplo 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 ajude

    Editar

    Como Daniel observou, você deve estar em conformidade com o UIGestureRecognizerDelegate para que ele funcione.

    Shani

    Eu também tive o mesmo problema, então eu tentei com

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

    Está funcionando agora perfeitamente ………

    De um modo geral, usamos abaixo o método delegate para evitar o toque em todos os tipos de UIControls:

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

    Nota: NÃO faça esta verificação (verifique o tipo de class recognizer.view) o gestureReconognizerShouldBegin, não funcionará.

    Aqui está uma versão do Swift 3.0 :

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

    Não esqueça de:

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

    Aqui está uma versão do Swift:

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

    Não esqueça de:

    1. Faça com que você esteja em conformidade com o UIGestureRecognizerDelegate
    2. Faça o seu object de tapper delegar para si mesmo (por exemplo: tapper.delegate = self )

    A melhor solução é para mim usar o snippet de código abaixo:

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