UILongPressGestureRecognizer é chamado duas vezes ao pressionar

359

Estou detectando se o usuário pressionou por 2 segundos:

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                             initWithTarget:self 
                                             action:@selector(handleLongPress:)];
        longPress.minimumPressDuration = 2.0;
        [self addGestureRecognizer:longPress];
        [longPress release];

É assim que lida com a pressão longa:

-(void)handleLongPress:(UILongPressGestureRecognizer*)recognizer{
    NSLog(@"double oo");
}

O texto "double oo" é impresso duas vezes quando pressiono por mais de 2 segundos. Por que é isso? Como posso corrigir?

Sheehan Alam
fonte

Respostas:

684

UILongPressGestureRecognizer é um reconhecedor contínuo de eventos. Você precisa observar o estado para ver se esse é o início, o meio ou o fim do evento e agir de acordo. ou seja, você pode jogar fora todos os eventos após o início ou apenas olhar o movimento conforme necessário. Da referência da classe :

Gestos de pressão longa são contínuos. O gesto começa (UIGestureRecognizerStateBegan) quando o número de dedos permitidos (numberOfTouchesRequired) foi pressionado pelo período especificado (minimumPressDuration) e os toques não ultrapassam a faixa de movimento permitida (allowableMovement). O reconhecedor de gestos passa para o estado Alterar sempre que um dedo se move e termina (UIGestureRecognizerStateEnded) quando qualquer um dos dedos é levantado.

Agora você pode acompanhar o estado como este

-  (void)handleLongPress:(UILongPressGestureRecognizer*)sender { 
    if (sender.state == UIGestureRecognizerStateEnded) {
      NSLog(@"UIGestureRecognizerStateEnded");
    //Do Whatever You want on End of Gesture
     }
    else if (sender.state == UIGestureRecognizerStateBegan){
       NSLog(@"UIGestureRecognizerStateBegan.");
   //Do Whatever You want on Began of Gesture
     }
  }
joelm
fonte
4
A próxima resposta abaixo mostra como fazê-lo, mas dei +1 a essa resposta por causa de sua explicação detalhada e link para a documentação.
Matt Connolly
2
Pode ser mais útil com um exemplo de código, em vez de vincular apenas à documentação. Publiquei meu snippet de código abaixo. verifique o estado UIGestureRecognizerStateBegan.
Paul Solt
UIGestureRecognizerStateChanged
Rajneesh071
@joelm você me salvou)
Evgeniy Kleban
Para Swift 4: if (sender.state == UITapGestureRecognizer.State.ended) {// Faça o que você quiser no final do gesto print ("\ n * longpressed * \ n")}
Ravi
117

Para verificar o estado do UILongPressGestureRecognizer, adicione uma instrução if no método seletor:

- (void)handleLongPress:(UILongPressGestureRecognizer *)sender {    
    if (sender.state == UIGestureRecognizerStateEnded) {
        NSLog(@"Long press Ended");
    } else if (sender.state == UIGestureRecognizerStateBegan) {
        NSLog(@"Long press detected.");
    }
}
Dan
fonte
13
Você não deseja esse bloco if / else, pois há mais estados que Ended. "Pressão longa detectada" será impressa várias vezes quando o estado for alterado. Verifique o estado UIGestureRecognizerStateBegan.
Paul Solt
2
Alguém realmente deve editar essa resposta para se adequar ao que o comentário principal diz. Tal como está, o código fornecido não funciona.
Declan McKenna
75

Você precisa verificar o estado correto, pois existem comportamentos diferentes para cada estado. Muito provavelmente você precisará do UIGestureRecognizerStateBeganestado com o UILongPressGestureRecognizer.

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                             initWithTarget:self 
                                             action:@selector(handleLongPress:)];
longPress.minimumPressDuration = 1.0;
[myView addGestureRecognizer:longPress];
[longPress release];

...

- (void)handleLongPress:(UILongPressGestureRecognizer *)gesture {
    if(UIGestureRecognizerStateBegan == gesture.state) {
        // Called on start of gesture, do work here
    }

    if(UIGestureRecognizerStateChanged == gesture.state) {
        // Do repeated work here (repeats continuously) while finger is down
    }

    if(UIGestureRecognizerStateEnded == gesture.state) {
        // Do end work here when finger is lifted
    }
}
Paul Solt
fonte
2
Parece que você precisa mexer os dedos para que o estado mude; isso está correto?
Arcadian
Pode acionar StateChanged ao mover os dedos, que soa semelhante ao que eu estava fazendo no meu código de teste.
Paul Solt
O UIGestureRecognizerStateBegan parece ser chamado apenas uma vez, o que é perfeito para a minha situação, tentando mostrar uma caixa de diálogo sobre a detecção de um toque longo em um botão. Os outros estados são chamados várias vezes. Obrigado!
21812 Damian
19

Apenas tente o seguinte:

Objetivo-C

- (void)handleLongPress:(UILongPressGestureRecognizer*)sender { 
    if (sender.state == UIGestureRecognizerStateEnded) {
        NSLog(@"Long press Ended");
    } else if (sender.state == UIGestureRecognizerStateBegan) {
        NSLog(@"Long press detected.");
    }
}

Swift 2.2:

func handleLongPress(sender:UILongPressGestureRecognizer) {

        if (sender.state == UIGestureRecognizerState.Ended) {
            print("Long press Ended");
        } else if (sender.state == UIGestureRecognizerState.Began) {
            print("Long press detected.");
        }
}
Rajesh Loganathan
fonte
14

Veja como lidar com isso no Swift:

func longPress(sender:UILongPressGestureRecognizer!) {

        if (sender.state == UIGestureRecognizerState.Ended) {
            println("Long press Ended");
        } else if (sender.state == UIGestureRecognizerState.Began) {
            println("Long press detected.");
        }
}
Raj
fonte
13

Swift 3.0:

func handleLongPress(sender: UILongPressGestureRecognizer) {

    if sender.state == .ended {
        print("Long press Ended")
    } else if sender.state == .began {
        print("Long press detected")
    }
fozoglu
fonte
6

seu manipulador de gestos recebe chamadas para cada estado de gesto. então você precisa marcar um estado para cada estado e colocar seu código no estado necessário.

É preciso preferir usar caso de comutação sobre if-else:

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                         initWithTarget:self 
                                         action:@selector(handleLongPress:)];
    longPress.minimumPressDuration = 1.0;
    [myView addGestureRecognizer:longPress];
    [longPress release];

-(void)handleLongPress:(UILongPressGestureRecognizer *)gesture {
        switch(gesture.state){
          case UIGestureRecognizerStateBegan:
               NSLog(@"State Began");
               break;
          case UIGestureRecognizerStateChanged:
               NSLog(@"State changed");
               break;
          case UIGestureRecognizerStateEnded:
               NSLog(@"State End");
               break;
          default:
               break;
         }
}
Pankaj Wadhwa
fonte