2009-10-17 8 views
7

Ho un NSTimer che genera un intervallo di 3 secondi per ridurre un valore. Quando eseguo un'azione che aumenta tale valore, voglio riavviare il timer per contare 3 secondi da quel punto.Ripristinare il tempo di attivazione di NSTimer da ora anziché l'ultimo incendio

Ad esempio, se si aumenta il valore e il timer scatta in 1 secondo, voglio cambiarlo e far scattare il timer in 3 secondi. Posso invalidare il timer e crearlo di nuovo? O posso farlo con setFireDate:, usando la data corrente e aggiungendo un intervallo di 3 secondi?

+0

Infine utilizzo setFireWithDate, quando aumento il valore invio anche un messaggio al timer con la data corrente più tre secondi. Funziona ^^ Grazie mille a tutti. – emenegro

risposta

7

Sì, è possibile invalidarlo. E crea di nuovo.

È anche possibile utilizzare:

- (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]; 

} 

vi chiamo myTimedTask per avviare l'attività ricorrente. Una volta avviato, è possibile modificare il ritardo con varyingDelay o interromperlo con weStillWantTimer.

+0

+1, ma certamente non un * globale *, giusto? :) – zoul

+0

@zoul, dipende da quanto vuoi essere disordinato :-) – mahboudz

1

Invalidare il timer e ricrearlo. Tuttavia, assicurarsi di non invalidare e rilasciare il timer a meno che non si sia certi di aver bisogno dal momento che il ciclo di esecuzione conserva i timer finché non vengono invalidati e quindi li rilascia da sé.

A mio parere, il codice di missaggio -performSelector con codice timer porta a un'esecuzione multipla dei metodi di destinazione, quindi starei lontano da quello.

1

Sì, l'annullamento e la ricreazione del timer funzioneranno. È essenzialmente ciò che si vuole fare se non si aumenta il valore: resettare e ricominciare.

1

I setFireDate: documenti menzionano che cambiare la data del fuoco è relativamente costoso, il che suggerisce che può essere meglio per distruggere e ricreare il timer a meno che non si sta facendo in modo molto. Per amor di discussione, tuttavia, ho montato questa categoria poco fa. Preferisco questo perché incapsula il comportamento di regolazione della data; il timer stesso lo gestisce, piuttosto che il suo proprietario/controller. Non ho dati sulle prestazioni su questo, però.

@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 

Ho usato le funzioni fondamentali della Fondazione solo per evitare la creazione di un NSDate. Ottimizzazione prematura? Per favore, passa il sale.

3

Ho eseguito un piccolo test e risulta che reimpostare il fireDate è circa quattro volte più veloce dell'invalidazione e della ricreazione del timer. In primo luogo, creo un timer che chiama il metodo DoNothing:

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

Ecco il codice di prova:

- (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]; 
     } 
    } 
} 

esecuzione che in un Air iPad cede 0.198173 s per invalidatingTimer e 0.044207 s per resettingTimer. Se la prestazione è il tuo obiettivo, ti consiglio di ripristinare il fireDate. È anche un po 'meno lo sforzo di codifica.

Problemi correlati