2010-01-03 12 views
22

Ho quasi finito con la mia app e il beta test ha rilevato un bug nella parte del cronometro ... Il cronometro usa un nstimer per fare il conteggio e ha una tabella per memorizzare giri, ma quando si scorre il lap table, l'orologio si ferma o si ferma e non recupera il tempo perduto.NSTimer non si attiva quando il runloop è bloccato

Questa è stata la paralisi è stato eliminato utilizzando:

startingTime = [[NSDate date] timeIntervalSince1970]; 

per calcolare il tempo trascorso.

ma sto ancora utilizzando il NSTimer per attivare ogni 0.1 secondi e ciò significa che lo scorrimento blocca ancora il timer anche se il tempo trascorso verrà aggiornato correttamente alla fine ... e confrontandolo con il cronometro Apple che fa Mi chiedo se quel cronometro ha una discussione separata solo per il conteggio del tempo trascorso. Qualcuno sa se è così che è fatto?

Ora, utilizzando il tempo dal momento che l'Epoch sta lavorando bene in un certo senso, ma si complica la questione di avviamento, arresto, & riavviare il cronometro

quando l'orologio viene fermato il tempo viene immagazzinato e utilizzato per calcolare un offset per quando l'orologio viene riavviato, ma sembra esserci un po 'di latenza introdotta e il tempo scorre visibilmente quando l'orologio viene riavviato.

Qualsiasi pensiero verso la causa principale o una soluzione sarebbe molto apprezzato.

risposta

22

Se il ciclo di eventi non è in esecuzione, i timer non verranno attivati ​​fino a quando il ciclo di eventi non potrà essere eseguito nuovamente. Anche se il ciclo degli eventi non è un blocco, il timer non è garantito per sparare esattamente al suo intervallo configurato. Se i tempi sono basati interamente sull'attivazione dei timer, l'ammontare dell'errore aumenterà nel tempo.

È necessario tenere traccia della durata separatamente dall'attivazione dei timer. Ogni volta che scatta un timer, ricalcoli la durata e visualizzi nuovamente.

Per iniziare/pausa/riavvio/tipo di installazione fermare, in genere si desidera:

  • afferrare il tempo all'avvio (o come un'istanza NSDate o in valore NSTimeInterval)

  • in pausa o stop, prendi il tempo in pausa/stop. Sottrarre l'ora di inizio da questo momento e di avere la durata del dell'intervallo

  • dopo il riavvio, afferrare il tempo al riavvio ma anche mantenere tutto il periodo già trascorso

  • su di pausa/stop, afferrare il tempo in pausa/stop e aggiungere la durata già trascorso

In generale, facendo tutto questo con valori NSTimeInterval - che sono solo raddoppia - è più facile. Tuttavia, se è necessario tenere traccia del momento effettivo nel momento in cui si verificano gli eventi, utilizzare invece le istanze di NSDate.

46

La risposta di bbum offre un modo migliore per progettare l'applicazione, ma se si desidera che il timer si accenda indipendentemente dal fatto che l'utente stia manipolando l'interfaccia utente o meno, sarà necessario aggiungerlo alla modalità di tracciamento del runloop.

Supponendo che si sta sviluppando per l'iPhone, quella modalità è UITrackingRunLoopMode. Se stai sviluppando per il Mac, c'è lo stesso nome NSEventTrackingRunLoopMode.

NSRunLoop *runloop = [NSRunLoop currentRunLoop]; 
NSTimer *timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(myTimerAction:) userInfo:nil repeats:YES]; 
[runloop addTimer:timer forMode:NSRunLoopCommonModes]; 
[runloop addTimer:timer forMode:UITrackingRunLoopMode]; 
+1

Ciò non garantisce ancora la precisione del tempo complessivo. I timer non sono garantiti per sparare esattamente al loro intervallo configurato. Peggio ancora, se ogni attivazione del timer si aggiunge all'intervallo complessivo, la quantità di errore aumenterà ad ogni accensione del timer! – bbum

+0

Non intendevo sostenere che avrebbero garantito qualcosa di diverso dai timer che avrebbero sparato mentre i controlli stavano monitorando. Memorizzare la data all'inizio del giro e utilizzarla per calcolare il tempo trascorso è molto più accurata (e più semplice IMO) che hai indicato nella risposta. –

+0

+1 ha funzionato per me. la risposta di bbum non aveva alcun senso per me. – bentford

Problemi correlati