Czy istnieje łatwy sposób na bardzo dokładne określenie czasu?
Muszę obliczyć pewne opóźnienia między wywołaniami metod. Dokładniej, chcę obliczyć szybkość przewijania w UIScrollView.
iphone
objective-c
cocoa-touch
uikit
Dzięki
źródło
źródło
Odpowiedzi:
NSDate
atimeIntervalSince*
metody zwrócąNSTimeInterval
wartość podwójną z dokładnością poniżej milisekundy.NSTimeInterval
zajmuje kilka sekund, ale używa podwójnej wartości, aby zapewnić większą precyzję.Aby obliczyć dokładność milisekundową, możesz wykonać:
Dokumentacja na czasIntervalSinceNow .
Istnieje wiele innych sposobów obliczania tego przedziału za pomocą
NSDate
i polecam przejrzenie dokumentacji klas, dlaNSDate
której można znaleźć w NSDate Class Reference .źródło
NSDate
imach_absolute_time()
na poziomie około 30 ms. 27 vs. 29, 36 vs. 39, 43 vs. 45.NSDate
było dla mnie łatwiejsze w użyciu, a wyniki były na tyle podobne, że nie przejmowałem się.mach_absolute_time()
można wykorzystać do uzyskania precyzyjnych pomiarów.Zobacz http://developer.apple.com/qa/qa2004/qa1398.html
Dostępny jest również
CACurrentMediaTime()
, który jest zasadniczo tym samym, ale z łatwiejszym w użyciu interfejsem.(Uwaga: ta odpowiedź została napisana w 2009 roku. Zobacz odpowiedź Pawła Aleksiejewa na temat prostszych
clock_gettime()
interfejsów POSIX dostępnych w nowszych wersjach macOS i iOS).źródło
CACurrentMediaTime()
, która konwertujemach_absolute_time()
bezpośrednio na plikdouble
.elapsedNano
jest typuNanoseconds
, który nie jest zwykłą liczbą całkowitą. Jest to alias programuUnsignedWide
, który jest strukturą z dwoma 32-bitowymi polami całkowitymi.UnsignedWideToUInt64()
Jeśli wolisz, możesz użyć zamiast obsady.Proszę nie używać
NSDate
,CFAbsoluteTimeGetCurrent
lubgettimeofday
zmierzyć czas, który upłynął. Wszystko to zależy od zegara systemowego, który może się zmienić w dowolnym momencie z wielu różnych powodów, takich jak synchronizacja czasu sieciowego (NTP), aktualizacja zegara (często w celu dostosowania do dryfu), regulacja czasu letniego, sekundy przestępne i tak dalej.Oznacza to, że jeśli mierzysz prędkość pobierania lub wysyłania, otrzymasz nagłe skoki lub spadki liczb, które nie są powiązane z tym, co faktycznie się wydarzyło; twoje testy wydajności będą miały dziwne, nieprawidłowe wartości odstające; a ręczne zegary uruchomią się po nieprawidłowym czasie trwania. Czas może nawet cofnąć się, a skończysz z ujemnymi deltami i możesz skończyć z nieskończoną rekurencją lub martwym kodem (tak, zrobiłem oba te).
Użyj
mach_absolute_time
. Mierzy rzeczywiste sekundy od momentu uruchomienia jądra. Zwiększa się monotonicznie (nigdy nie cofa się) i nie ma na nie wpływu ustawienia daty i godziny. Ponieważ praca z nią jest trudna, oto proste opakowanie, które dajeNSTimeInterval
:źródło
CACurrentMediaTime()
z QuartzCore?@import Darwin;
zamiast#include <mach/mach_time.h>
CFAbsoluteTimeGetCurrent()
zwraca bezwzględny czas jakodouble
wartość, ale nie wiem, jaka jest jego dokładność - może aktualizować się tylko co kilkanaście milisekund lub może aktualizować co mikrosekundę, nie wiem.źródło
72.89674947369
sekund byłaby dość rzadka, biorąc pod uwagę wszystkie inne wartości, które mogłyby to być. ;)NIE użyłbym,
mach_absolute_time()
ponieważ pyta o kombinację jądra i procesora przez absolutny czas za pomocą tików (prawdopodobnie uptime).Czego bym użył:
Ta funkcja jest zoptymalizowana pod kątem korygowania różnic w oprogramowaniu i sprzęcie iOS i OSX.
Coś bardziej geekowskiego
Iloraz różnicy
mach_absolute_time()
iAFAbsoluteTimeGetCurrent()
jest zawsze wokół 24000011.154871Oto dziennik mojej aplikacji:
Należy pamiętać, że końcowy wynik jest czas różnica w
CFAbsoluteTimeGetCurrent()
„sźródło
mach_absolute_time()
z a,mach_timebase_info_data
a potem zrobiłem(long double)((mach_absolute_time()*time_base.numer)/((1000*1000)*time_base.denom));
. Aby uzyskać(void)mach_timebase_info(&your_timebase);
Stosowanie:
Wynik:
źródło
NSDate
zależy od zegara systemowego, który można zmienić w dowolnym momencie, potencjalnie powodując błędne lub nawet ujemne odstępy czasu. Użyjmach_absolute_time
zamiast tego, aby uzyskać prawidłowy czas, który upłynął.mach_absolute_time
może mieć wpływ na ponowne uruchomienie urządzenia. Zamiast tego użyj czasu serwera.Tutaj jest również sposób obliczania 64-bitowego
NSNumber
zainicjowanego z epoką Uniksa w milisekundach, na wypadek, gdyby tak było w przypadku przechowywania w CoreData. Potrzebowałem tego dla mojej aplikacji, która współpracuje z systemem przechowującym daty w ten sposób.źródło
Oparte na
mach_absolute_time
nich funkcje nadają się do krótkich pomiarów.Ale w przypadku długich pomiarów ważnym zastrzeżeniem jest to, że przestają tykać, gdy urządzenie śpi.
Istnieje funkcja pozwalająca uzyskać czas od momentu uruchomienia. Nie zatrzymuje się podczas snu. Nie
gettimeofday
jest też monotoniczny, ale w moich eksperymentach zawsze widziałem, że czas uruchamiania zmienia się wraz ze zmianą czasu systemowego, więc myślę, że powinien działać dobrze.A od iOS 10 i macOS 10.12 możemy korzystać z CLOCK_MONOTONIC:
Podsumowując:
Date.timeIntervalSinceReferenceDate
- zmienia się wraz ze zmianą czasu systemowego, a nie monotonicznieCFAbsoluteTimeGetCurrent()
- nie monotonna, może cofać sięCACurrentMediaTime()
- przestaje tykać, gdy urządzenie śpitimeSinceBoot()
- nie śpi, ale może nie być monotonnyCLOCK_MONOTONIC
- nie śpi, monotonicznie, obsługiwane od iOS 10źródło
Wiem, że jest to stara, ale nawet ja ponownie przechodzę obok niej, więc pomyślałem, że przedstawię tutaj własną opcję.
Najlepiej sprawdzić mój wpis na blogu na ten temat: Czas rzeczy w Objective-C: Stoper
Zasadniczo napisałem zajęcia, które przestają oglądać w bardzo prosty sposób, ale są zamknięte, więc wystarczy wykonać następujące czynności:
Otrzymujesz:
w dzienniku ...
Ponownie, sprawdź mój post po trochę więcej lub pobierz go tutaj: MMStopwatch.zip
źródło
NSDate
zależy od zegara systemowego, który można zmienić w dowolnym momencie, potencjalnie powodując błędne lub nawet ujemne odstępy czasu. Użyjmach_absolute_time
zamiast tego, aby uzyskać prawidłowy czas, który upłynął.Możesz uzyskać aktualny czas w milisekundach od 1 stycznia 1970 roku za pomocą NSDate:
źródło
Dla tych potrzebujemy szybkiej wersji odpowiedzi @Jeff Thompson:
Mam nadzieję, że to ci pomoże.
źródło
NSDate
zależy od zegara systemowego, który można zmienić w dowolnym momencie, potencjalnie powodując błędne lub nawet ujemne odstępy czasu. Użyjmach_absolute_time
zamiast tego, aby uzyskać prawidłowy czas, który upłynął.