¿Existe una manera fácil de obtener una hora con mucha precisión?
Necesito calcular algunos retrasos entre las llamadas al método. Más específicamente, quiero calcular la velocidad de desplazamiento en un UIScrollView.
iphone
objective-c
cocoa-touch
uikit
Gracias
fuente
fuente
Respuestas:
NSDate
y lostimeIntervalSince*
métodos devolverán unNSTimeInterval
que es un doble con una precisión de menos de milisegundos.NSTimeInterval
está en segundos, pero usa el doble para darle mayor precisión.Para calcular la precisión de tiempo de milisegundos, puede hacer:
Documentación en timeIntervalSinceNow .
Hay muchas otras formas de calcular este intervalo utilizando
NSDate
, y recomendaría mirar la documentación de la claseNSDate
que se encuentra en NSDate Class Reference .fuente
NSDate
ymach_absolute_time()
en un nivel de alrededor de 30 ms. 27 vs. 29, 36 vs. 39, 43 vs. 45.NSDate
fue más fácil de usar para mí y los resultados fueron lo suficientemente similares como para no importarme.mach_absolute_time()
se puede utilizar para obtener medidas precisas.Ver http://developer.apple.com/qa/qa2004/qa1398.html
También está disponible
CACurrentMediaTime()
, que es esencialmente lo mismo pero con una interfaz más fácil de usar.(Nota: esta respuesta se escribió en 2009. Consulte la respuesta de Pavel Alexeev para conocer las
clock_gettime()
interfaces POSIX más simples disponibles en las versiones más recientes de macOS e iOS).fuente
CACurrentMediaTime()
, que se conviertemach_absolute_time()
directamente en undouble
.elapsedNano
es de tipoNanoseconds
, que no es un tipo entero simple. Es un alias deUnsignedWide
, que es una estructura con dos campos enteros de 32 bits. Puede usar enUnsignedWideToUInt64()
lugar del yeso si lo prefiere.No utilice
NSDate
,CFAbsoluteTimeGetCurrent
nigettimeofday
para medir el tiempo transcurrido. Todo esto depende del reloj del sistema, que puede cambiar en cualquier momento debido a muchas razones diferentes, como la sincronización de la hora de la red (NTP), la actualización del reloj (sucede a menudo para ajustar la desviación), los ajustes de DST, los segundos intercalares, etc.Esto significa que si está midiendo su velocidad de descarga o carga, obtendrá picos o caídas repentinas en sus números que no se correlacionan con lo que realmente sucedió; sus pruebas de rendimiento tendrán valores atípicos incorrectos extraños; y sus temporizadores manuales se activarán después de duraciones incorrectas. El tiempo puede incluso retroceder y terminar con deltas negativos, y puede terminar con una recursividad infinita o un código muerto (sí, he hecho ambos).
Utilice
mach_absolute_time
. Mide los segundos reales desde que se inició el kernel. Está aumentando monótonamente (nunca retrocederá) y no se ve afectado por los ajustes de fecha y hora. Dado que es difícil trabajar con él, aquí hay un envoltorio simple que le brindaNSTimeInterval
s:fuente
CACurrentMediaTime()
con QuartzCore?@import Darwin;
lugar de#include <mach/mach_time.h>
CFAbsoluteTimeGetCurrent()
devuelve el tiempo absoluto comodouble
valor, pero no sé cuál es su precisión: puede que solo se actualice cada docena de milisegundos, o podría actualizar cada microsegundo, no lo sé.fuente
72.89674947369
segundos sería bastante poco común, considerando todos los demás valores que podría ser. ;)NO lo usaría
mach_absolute_time()
porque consulta una combinación del kernel y el procesador durante un tiempo absoluto usando ticks (probablemente un tiempo de actividad).Qué usaría:
Esta función está optimizada para corregir la diferencia en el software y hardware iOS y OSX.
Algo más geek
El cociente de una diferencia en
mach_absolute_time()
yAFAbsoluteTimeGetCurrent()
siempre está alrededor de 24000011.154871Aquí hay un registro de mi aplicación:
Por favor nota que el tiempo resultado final es una diferencia en
CFAbsoluteTimeGetCurrent()
'sfuente
mach_absolute_time()
con amach_timebase_info_data
y luego lo hice(long double)((mach_absolute_time()*time_base.numer)/((1000*1000)*time_base.denom));
. Para obtener la base de tiempo de Mach, puede hacerlo(void)mach_timebase_info(&your_timebase);
Uso:
Salida:
fuente
NSDate
depende del reloj del sistema, que puede modificarse en cualquier momento, lo que puede dar lugar a intervalos de tiempo incorrectos o incluso negativos. Úselo en sumach_absolute_time
lugar para obtener el tiempo transcurrido correcto.mach_absolute_time
puede verse afectado por los reinicios del dispositivo. En su lugar, utilice la hora del servidor.Además, aquí se explica cómo calcular un 64 bits
NSNumber
inicializado con la época de Unix en milisegundos, en caso de que así sea como desee almacenarlo en CoreData. Necesitaba esto para mi aplicación que interactúa con un sistema que almacena fechas de esta manera.fuente
Las funciones basadas en
mach_absolute_time
son buenas para mediciones cortas.Pero para mediciones largas, una advertencia importante es que dejan de hacer tictac mientras el dispositivo está inactivo.
Hay una función para obtener el tiempo desde el inicio. No se detiene mientras duerme. Además,
gettimeofday
no es monótono, pero en mis experimentos siempre he visto que el tiempo de arranque cambia cuando cambia el tiempo del sistema, así que creo que debería funcionar bien.Y desde iOS 10 y macOS 10.12 podemos usar CLOCK_MONOTONIC:
Para resumirlo:
Date.timeIntervalSinceReferenceDate
- cambia cuando cambia la hora del sistema, no monótonoCFAbsoluteTimeGetCurrent()
- no monótono, puede retrocederCACurrentMediaTime()
- deja de hacer tictac cuando el dispositivo está dormidotimeSinceBoot()
- no duerme, pero puede que no sea monótonoCLOCK_MONOTONIC
- no duerme, monótono, compatible desde iOS 10fuente
Sé que este es antiguo, pero incluso yo me encontré vagando de nuevo, así que pensé en enviar mi propia opción aquí.
La mejor opción es consultar mi publicación de blog sobre esto: cronometraje en Objective-C: un cronómetro
Básicamente, escribí una clase que deja de mirar de una manera muy básica, pero está encapsulada, por lo que solo necesita hacer lo siguiente:
Y terminas con:
en el registro ...
Una vez más, consulte mi publicación para obtener más información o descárguela aquí: MMStopwatch.zip
fuente
NSDate
depende del reloj del sistema, que puede modificarse en cualquier momento, lo que puede dar lugar a intervalos de tiempo incorrectos o incluso negativos. Úselo en sumach_absolute_time
lugar para obtener el tiempo transcurrido correcto.Puede obtener la hora actual en milisegundos desde el 1 de enero de 1970 utilizando un NSDate:
fuente
Para aquellos, necesitamos la versión Swift de la respuesta de @Jeff Thompson:
Espero que esto te ayude.
fuente
NSDate
depende del reloj del sistema, que puede modificarse en cualquier momento, lo que puede dar lugar a intervalos de tiempo incorrectos o incluso negativos. Úselo en sumach_absolute_time
lugar para obtener el tiempo transcurrido correcto.