2011-12-27 4 views
6

Estoy trabajando en mi primera aplicación de iOS y me he encontrado con la primera pega para la que no he podido encontrar una buena respuesta.Objetivo C y iOS: ¿ejecuta un temporizador? NSTimer/Threads/NSDate/etc

El problema: tengo un UIGestureRecognizer personalizado y lo tengo todo cableado correctamente, y puedo ejecutar el código para cada toque en el @selector después del reconocimiento. Esto ha estado bien para la mayoría de las cosas, pero es un poco demasiado para otros.

Mi objetivo: hacer que un temporizador que se dispara en un intervalo especificado ejecute la lógica, y poder cancelar esto en el momento en que se cancelan los toques.

Por qué lo estoy preguntando aquí: Hay muchas posibilidades para las soluciones, pero ninguna se ha destacado como la mejor para implementar. Hasta ahora parece que

  • performSelector (y algunas variaciones sobre este)
  • NSThread
  • NSTimer
  • NSDate
  • Operación colas
  • Creo que he encontrado algunos otros también ...

De toda la investigación, alguna forma de hacer un hilo parece ser el camino a seguir, pero estoy en una pérdida en la que funcionaría mejor para esta situación.

Un ejemplo de una implementación: un NSPoint se toma cada 0,10 segundos, y se toma la distancia entre el punto anterior y el actual. [Tomando la distancia entre cada punto estaba dando resultados muy desordenados].

El código relevante:

- (void)viewDidLoad { 
CUIVerticalSwipeHold *vSwipe = 
[[CUIVerticalSwipeHold alloc] 
initWithTarget:self 
action:@selector(touchHoldMove:)]; 
[self.view addGestureRecognizer:vSwipe]; 
[vSwipe requireGestureRecognizerToFail:doubleTap]; 
} 

... 

- (IBAction)touchHoldMove:(UIGestureRecognizer *)sender { 
    if (sender.state == UIGestureRecognizerStateEnded) { 

    } 

    if (sender.state == UIGestureRecognizerStateBegan) { 

    } 

    //other stuff to do goes here 

} 

Respuesta

11

Utilice un NSTimer

Conjunto que de esta manera:

theTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(yourMethodThatYouWantRunEachTimeTheTimerFires) userInfo:nil repeats:YES]; 

A continuación, cuando se quiere cancelarlo, hacer algo como esto:

if ([theTimer isValid]) 
{ 
    [theTimer invalidate]; 
} 

Tenga en cuenta que en el ejemplo anterior, deberá declarar la instancia "theTimer" de NSTimer, donde estará disponible para ambos métodos. En el ejemplo anterior, el "0.5" significa que el temporizador disparará dos veces por segundo. Ajustar según sea necesario.

+1

Nota: Se considera buena práctica establecer el temporizador en cero después de invalidarlo: [el temporizador invalida]; theTimer = nil; – Groot

1

En aras de la exhaustividad, añado mi implementación final aquí (no estoy seguro que este es el modo de hacerlo, pero aquí va)

.h

@interface { 
    NSTimer *myTimer; 
} 

@property (nonatomic, retain) NSTimer *myTimer; 

.m

@synthesize myTimer; 

------------------------------------------- 

- (void)viewDidLoad { 
//Relevant snipet 
CUIVerticalSwipeHold *vSwipe = 
[[CUIVerticalSwipeHold alloc] 
initWithTarget:self 
action:@selector(touchHoldMove:)]; 
[self.view addGestureRecognizer:vSwipe]; 
[vSwipe requireGestureRecognizerToFail:doubleTap]; 
} 

------------------------------------------- 

- (IBAction)touchHoldMove:(UIGestureRecognizer *)sender { 
    if (sender.state == UIGestureRecognizerStateEnded) { 
     //Cancel the timer when the gesture ends 
     if ([myTimer isValid]) 
      { 
       [myTimer invalidate]; 
      } 
     } 
    } 

    if (sender.state == UIGestureRecognizerStateBegan) { 
     //starting the timer when the gesture begins 
     myTimer = [NSTimer scheduledTimerWithTimeInterval:someTimeIncrement 
                target:self 
               selector:@selector(someSelector) 
               userInfo:nil 
                repeats:YES]; 
    } 
}