2009-10-17 14 views
7

Tengo un NSTimer que se dispara con un intervalo de 3 segundos para disminuir un valor. Cuando realizo una acción que aumenta ese valor, quiero reiniciar el temporizador para contar 3 segundos desde ese punto.Restablecer el tiempo de disparo de un NSTimer para que sea a partir de ahora en lugar del último incendio

Por ejemplo, si aumento el valor y el temporizador se dispara en 1 segundo, quiero cambiar eso y hacer que el temporizador se active en 3 segundos. ¿Puedo invalidar el cronómetro y volver a crearlo? ¿O puedo hacerlo con setFireDate:, usando la fecha actual y agregando un intervalo de 3 segundos?

+0

Finalmente uso setFireWithDate, cuando aumento el valor, también envío un mensaje al cronómetro con la fecha actual más tres segundos. Funciona ^^ Muchas gracias en absoluto. – emenegro

Respuesta

7

Sí, puede invalidarlo. Y créelo de nuevo.

También puede utilizar:

- (void) myTimedTask { 
    // other stuff this task needs to do 

    // change the variable varyingDelay to be 1s or 3s or... This can be an instance variable or global that is changed by other parts of your app 
    // weStillWantTimer is also a similar variable that your app uses to stop this recurring task 

if (weStillWantTimer) 
     [self performSelector:@selector(myTimedTask:) withObject:gameColor afterDelay:varyingDelay]; 

} 

se llama a myTimedTask para iniciar la tarea recurrente. Una vez que se inicia, puede cambiar el retraso con varyDelay o detenerlo con weStillWantTimer.

+0

+1, pero ciertamente no es * global *, ¿verdad? :) – zoul

+0

@zoul, depende de lo desordenado que quieras estar :-) – mahboudz

1

Invalidar el temporizador y recrearlo. Sin embargo, asegúrese de no invalidar y suelte el temporizador a menos que esté seguro de que lo necesita, ya que el ciclo de ejecución conserva los temporizadores hasta que se invaliden y luego los libera.

En mi opinión, mezclar -perform El código de selección con código de temporizador lleva a la ejecución múltiple de los métodos de destino, así que me mantendría alejado de eso.

1

Sí, la invalidación y la recreación del temporizador funcionarán. Es esencialmente lo que quieres hacer si no estás aumentando tu valor: restablecer y comenzar de nuevo.

1

Los setFireDate: documentos mencionan que el cambio de la fecha de fuego es relativamente caro, lo que sugiere que puede ser mejor para destruir y recrear el temporizador menos que se haga de manera mucho. Por el bien de la discusión, sin embargo, abrí esta categoría hace un rato. Prefiero esto porque encapsula el comportamiento de ajuste de fecha; el propio temporizador lo maneja, en lugar de su propietario/controlador. Sin embargo, no tengo ningún dato de rendimiento sobre esto.

@implementation NSTimer (WSSAdjustingFireDate) 

- (void)WSSFireAdjustingFireDate 
{ 
    [self fire]; 

    [self WSSSkipNextFireAdjustingFireDate]; 
} 

- (void)WSSSkipNextFireAdjustingFireDate 
{ 
    CFRunLoopTimerRef cfSelf = (__bridge CFRunLoopTimerRef)self; 
    CFTimeInterval delay = CFRunLoopTimerGetInterval(cfSelf); 
    CFRunLoopTimerSetNextFireDate(cfSelf, CFAbsoluteTimeGetCurrent() + delay); 
} 

@end 

He utilizado las funciones de base fundamental sólo para evitar la creación de un NSDate. Optimización prematura? Por favor, pásame la sal.

3

He realizado algunas pruebas, y resulta que reiniciar fireDate es cuatro veces más rápido que invalidar y volver a crear el temporizador. En primer lugar, se crea un temporizador que llama al método DoNothing:

if (!testTimer) { 
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0 
                 target:self 
                selector:@selector(doNothing:) 
                userInfo:nil 
                repeats:NO]; 
    testTimer = timer; 
} 

Aquí está el código de prueba:

- (void) testInvalidatingTimer { 
    for (int n = 0; n < 10000; n++) { 
     [testTimer invalidate]; 
     testTimer = nil; 

     NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:3.0 
                  target:self 
                 selector:@selector(doNothing:) 
                 userInfo:nil 
                 repeats:NO]; 
     testTimer = timer; 
    } 
} 

- (void) testResettingTimer { 
    for (int n = 0; n < 10000; n++) { 
     if ([testTimer isValid]) { 
      testTimer.fireDate = [NSDate dateWithTimeIntervalSinceNow:3.0]; 
     } 
    } 
} 

Ejecución que un aire iPad produce 0.198173 s para invalidatingTimer y 0.044207 s para resettingTimer. Si el rendimiento es su objetivo, recomiendo restablecer el fireDate. También es bastante menos esfuerzo de codificación.

Cuestiones relacionadas