UILongPressGestureRecognizer recibe dos llamadas al presionar hacia abajo

359

Estoy detectando si el usuario ha presionado durante 2 segundos:

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

Así es como manejo la pulsación larga:

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

El texto "doble oo" se imprime dos veces cuando presiono durante más de 2 segundos. ¿Por qué es esto? ¿Cómo puedo arreglarlo?

Sheehan Alam
fuente

Respuestas:

684

UILongPressGestureRecognizer es un reconocedor de eventos continuo. Debe mirar el estado para ver si este es el inicio, el medio o el final del evento y actuar en consecuencia. es decir, puede tirar todos los eventos después del inicio, o solo mirar el movimiento según lo necesite. De la referencia de clase :

Los gestos de presión prolongada son continuos. El gesto comienza (UIGestureRecognizerStateBegan) cuando se ha presionado el número de dedos permitidos (numberOfTouchesRequired) durante el período especificado (mínimoPressDuration) y los toques no se mueven más allá del rango de movimiento permitido (movimiento permitido). El reconocedor de gestos pasa al estado Cambiar cada vez que se mueve un dedo y termina (UIGestureRecognizerStateEnded) cuando se levanta cualquiera de los dedos.

Ahora puedes rastrear el estado así

-  (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
fuente
44
La siguiente respuesta muestra cómo hacerlo, pero le di a esta respuesta el +1 debido a su explicación detallada y enlace a la documentación.
Matt Connolly
2
Podría ser más útil con un ejemplo de código, en lugar de vincular solo a la documentación. He publicado mi fragmento de código a continuación. verifique el estado UIGestureRecognizerStateBegan.
Paul Solt
UIGestureRecognizerStateChanged
Rajneesh071
@joelm me salvaste)
Evgeniy Kleban
Para Swift 4: if (sender.state == UITapGestureRecognizer.State.ended) {// Haz lo que quieras en la impresión de fin de gesto ("\ n * longpressed * \ n")}
Ravi
117

Para verificar el estado del UILongPressGestureRecognizer simplemente agregue una declaración if en el método selector:

- (void)handleLongPress:(UILongPressGestureRecognizer *)sender {    
    if (sender.state == UIGestureRecognizerStateEnded) {
        NSLog(@"Long press Ended");
    } else if (sender.state == UIGestureRecognizerStateBegan) {
        NSLog(@"Long press detected.");
    }
}
Dan
fuente
13
No quieres que bloquee si / si no, ya que hay más estados que Ended. "Pulsación larga detectada" se imprimirá varias veces cuando cambie el estado. Compruebe el estado UIGestureRecognizerStateBegan en su lugar.
Paul Solt
2
Alguien realmente debería editar esa respuesta para que se ajuste a lo que dice el comentario principal. Tal como está, el código proporcionado no funciona.
Declan McKenna
75

Debe verificar el estado correcto, ya que hay diferentes comportamientos para cada estado. Lo más probable es que necesites el UIGestureRecognizerStateBeganestado con el 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
fuente
2
Parece que tienes que mover los dedos para cambiar el estado; ¿Es eso correcto?
Arcadian
Puede activar StateChanged al mover los dedos, eso suena similar a lo que estaba haciendo en mi código de prueba.
Paul Solt
UIGestureRecognizerStateBegan parece que solo se llama una vez, lo cual es perfecto para mi situación al tratar de mostrar un cuadro de diálogo sobre la detección de una presión prolongada en un botón. Los otros estados se llaman varias veces. ¡Gracias!
Damian
19

Solo intenta esto:

C objetivo

- (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
fuente
14

Aquí se explica cómo manejarlo en 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
fuente
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
fuente
6

su gestor de gestos recibe llamadas para cada estado de gestos. por lo tanto, debe marcar cada estado y poner su código en el estado requerido.

Uno debe preferir usar switch-case 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
fuente