Po prostu nie masz żadnych gwarancji z NSTimer
lub dispatch_after
; Planują kod uruchamiany w głównym wątku, ale jeśli wykonanie i zablokowanie głównego wątku potrwa zbyt długo, twój timer się nie uruchomi.
Powiedziawszy, możesz łatwo uniknąć blokowania głównego wątku (używaj tylko asynchronicznych operacji we/wy) i rzeczy powinny być całkiem dobre.
Nie mówisz dokładnie, co musisz zrobić w kodzie timera, ale jeśli wszystko, co musisz zrobić, to wyświetlić odliczanie, powinieneś być w porządku, o ile obliczasz czas SMPTE w oparciu o czas systemowy, a nie liczba sekund, które Twoim zdaniem powinny upłynąć w oparciu o interwał czasomierza. Jeśli to zrobisz, prawie na pewno będziesz dryfować i tracić zsynchronizowanie z rzeczywistym czasem. Zamiast tego, należy pamiętać, czas rozpoczęcia, a następnie zrobić wszystko, matematyki w oparciu o które:
// Setup
timerStartDate = [[NSDate alloc] init];
[NSTimer scheduledTimer...
- (void)timerDidFire:(NSTimer *)timer
{
NSTImeInterval elapsed = [timerStartDate timeIntervalSinceNow];
NSString *smtpeCode = [self formatSMTPEFromMilliseconds:elapsed];
self.label.text = smtpeCode;
}
Teraz będzie wyświetlany poprawny kod czasu bez względu na to, jak często timer jest zwolniony. (Jeśli licznik czasu nie wystrzeli wystarczająco często, licznik czasu nie zaktualizuje się, ale gdy zostanie zaktualizowany, będzie dokładny, nigdy nie będzie się zsynchronizować.)
Jeśli używasz programu CADisplayLink, twoja metoda zostanie nazwana tak szybko, jak aktualizacja ekranu. Innymi słowy, tak szybko, jak byłoby to przydatne, ale nie szybciej. Jeśli wyświetlasz czas, prawdopodobnie jest to właściwy sposób.
Należy zauważyć, że element _frameInterval_ był nieaktualny w systemie iOS 10.0, użył _preferredFramesPerSecond_, tak jak poniżej: 'displayLink.preferredFramesPerSecond = 30.0;' dla 30 klatek na sekundę – WongWray