Básicamente no tiene garantías con NSTimer
o dispatch_after
; programan el código para que se active en el hilo principal, pero si algo más tarda en ejecutarse y bloquea el hilo principal, el temporizador no se disparará.
Dicho esto, puede evitar fácilmente el bloqueo del hilo principal (use solo E/S asincrónicas) y las cosas deberían ser bastante buenas.
No dice exactamente lo que necesita hacer en el código del temporizador, pero si todo lo que tiene que hacer es mostrar una cuenta atrás, debe estar bien siempre que calcule el tiempo SMPTE basado en la hora del sistema, y no la cantidad de segundos que cree que debería haber transcurrido según el intervalo de su temporizador. Si haces eso, es casi seguro que te desvíes y te desincronices con el tiempo real. En su lugar, indicar la hora de inicio y luego hacer todas las matemáticas basado en que:
// Setup
timerStartDate = [[NSDate alloc] init];
[NSTimer scheduledTimer...
- (void)timerDidFire:(NSTimer *)timer
{
NSTImeInterval elapsed = [timerStartDate timeIntervalSinceNow];
NSString *smtpeCode = [self formatSMTPEFromMilliseconds:elapsed];
self.label.text = smtpeCode;
}
Ahora se mostrará el código de tiempo correcto no importa cuántas veces se dispara el temporizador. (Si el temporizador no se dispara con la frecuencia suficiente, el temporizador no se actualizará, pero cuando se actualice será preciso. Nunca se desincronizará).
Si utiliza CADisplayLink, su método se llamará tan rápido como se actualice la pantalla. En otras palabras, tan rápido como sería útil, pero no más rápido. Si está mostrando la hora, ese es probablemente el camino a seguir.
Tenga en cuenta que _frameInterval_ está en desuso en iOS 10.0, use _preferredFramesPerSecond_, así: 'displayLink.preferredFramesPerSecond = 30.0;' para 30fps – WongWray