2010-01-03 22 views
22

Estoy a punto de terminar con mi aplicación y las pruebas beta encontraron un error en la parte del cronómetro ... El cronómetro usa un nstimer para contar y tiene una tabla para almacenar vueltas, pero cuando se desplaza la tabla de vueltas, el reloj se detiene o hace una pausa y no compensa el tiempo perdido.NSTimer no se dispara cuando runloop está bloqueado

Esto estaba haciendo tiempo fue eliminada mediante el uso de:

startingTime = [[NSDate date] timeIntervalSince1970]; 

para calcular el tiempo transcurrido.

pero todavía estoy usando el NSTimer para disparar cada 0.1 segundos y eso significa que el desplazamiento todavía detiene el temporizador aunque el tiempo transcurrido se actualizará correctamente al final ... y comparándolo con el cronómetro de Apple que hace Me pregunto si ese cronómetro tiene un hilo separado solo para el conteo del tiempo transcurrido. ¿Alguien sabe si así es como se hace?

Ahora, utilizando el tiempo desde la Época está funcionando bien en un sentido, pero complica la cuestión de cómo iniciar, detener, & reiniciar el cronómetro

cuando el reloj se detuvo el tiempo se almacena y se utiliza para calcular una compensación para cuando se reinicia el reloj, pero parece que se ha introducido algo de latencia y el tiempo avanza visiblemente cuando se reinicia el reloj.

Cualquier idea sobre la causa raíz o una solución sería muy apreciada.

Respuesta

22

Si el bucle de eventos no se está ejecutando, los temporizadores no se dispararán hasta que el bucle de eventos pueda volver a ejecutarse. Incluso si el bucle de evento no está bloqueado, no se garantiza que el temporizador se dispare exactamente a su intervalo configurado. Si sus tiempos se basan completamente en disparos de temporizadores, la cantidad de errores crecerá con el tiempo.

Debe realizar un seguimiento de la duración por separado del disparo de los temporizadores. Cada vez que se dispara un temporizador, vuelva a calcular su duración y vuelva a mostrarlo.

Para un comienzo/pausa/reinicio/parada tipo de configuración, por lo general quieren:

  • agarrar el tiempo en el arranque (ya sea como una instancia NSDate o como un valor NSTimeInterval)

  • al detenerse o detenerse, tome el tiempo en pausa/parada. Restar el tiempo de inicio de este tiempo y usted tiene la duración del intervalo de

  • al reiniciar, agarra el tiempo al reiniciar sino también mantener en torno a la duración ya transcurrido

  • en pausa/parada, tome el tiempo en pausa/parada y añadir la duración ya transcurrido

En general, hacer todo esto con los valores NSTimeInterval - que son simplemente duplica - es más fácil. Sin embargo, si necesita realizar un seguimiento del momento real en el momento en que ocurrieron los eventos, use las instancias NSDate en su lugar.

46

La respuesta de bbum proporciona una mejor manera de diseñar su aplicación, pero si desea que su temporizador se dispare independientemente de si el usuario está manipulando la interfaz de usuario o no, tendrá que agregarlo al modo de seguimiento del runloop.

Suponiendo que está desarrollando para el iPhone, ese modo es UITrackingRunLoopMode. Si está desarrollando para Mac existe un nombre similar llamado 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

Eso todavía no garantiza la precisión del tiempo total. No se garantiza que los temporizadores disparen exactamente a su intervalo configurado. Peor aún, si cada disparo de temporizador se suma al intervalo general, la cantidad de error aumentará con cada disparo de temporizador. – bbum

+0

No tenía la intención de argumentar que garantizarían nada más que los temporizadores dispararían mientras los controles estaban rastreando. Almacenar la fecha al inicio de la vuelta y usarla para calcular el tiempo transcurrido es mucho más precisa (y más sencilla) como lo había indicado en su respuesta. –

+0

+1 Funcionó para mí. La respuesta de bbum no tenía ningún sentido para mí. – bentford

Cuestiones relacionadas