Potrzebuję czasu, jaki upłynął między dwoma zdarzeniami, na przykład pojawieniem się UIView i pierwszą reakcją użytkownika.
Jak mogę to osiągnąć w Objective-C?
ios
objective-c
Ilya Suzdalnitski
źródło
źródło
fabs(...)
aby uzyskać wartość bezwzględną pływaka. Na przykład.NSTimeInterval timeInterval = fabs([start timeIntervalSinceNow]);
[NSDate date]
może prowadzić do trudnych do śledzenia błędów, zobacz tę odpowiedź, aby uzyskać więcej informacji.Nie należy polegać na
[NSDate date]
czasie, ponieważ może on zawyżać lub zaniżać czas, który upłynął. Istnieją nawet przypadki, w których twój komputer pozornie podróżuje w czasie, ponieważ upływający czas będzie ujemny! (Np. Jeśli zegar przesunął się do tyłu podczas pomiaru czasu).Według Arii Haghighi w wykładzie „Advanced iOS Gesture Recognition” na kursie Winter 2013 Stanford iOS (34:00),
CACurrentMediaTime()
jeśli potrzebujesz dokładnego interwału czasowego , powinieneś używać .Cel C:
Szybki:
Powodem jest to, że
[NSDate date]
synchronizuje się na serwerze, więc może to prowadzić do „problemów z synchronizacją czasu”, co może prowadzić do bardzo trudnych do śledzenia błędów.CACurrentMediaTime()
z drugiej strony jest to czas urządzenia, który nie zmienia się podczas tych synchronizacji sieciowych.Będziesz musiał dodać strukturę QuartzCore do ustawień celu.
źródło
[NSDate date]
w bloku uzupełniania w bloku wysyłania otrzymywałem ten sam „bieżący” czas, który był zgłaszany[NSDate date]
bezpośrednio przed wykonaniem punktu, w którym zostały utworzone moje bloki.CACurrentMediaTime()
rozwiązał ten problem.CACurrentMediaTime()
przestaje tykać, gdy urządzenie przechodzi w stan uśpienia. Jeśli testujesz urządzenie odłączone od komputera, zablokuj je, a następnie odczekaj ~ 10 minut, a okaże się, żeCACurrentMediaTime()
nie nadąża za zegarem ściennym.Użyj
timeIntervalSinceDate
metodyNSTimeInterval
to tylko adouble
, zdefiniuj wNSDate
ten sposób:źródło
Dla każdego, kto szuka implementacji getTickCount () dla iOS, oto moje po połączeniu różnych źródeł.
Wcześniej miałem błąd w tym kodzie (najpierw podzieliłem przez 1000000), który powodował kwantyzację danych wyjściowych na moim iPhonie 6 (być może nie był to problem na iPhonie 4 / itp. Lub po prostu nigdy tego nie zauważyłem). Zwróć uwagę, że nie wykonując najpierw tego podziału, istnieje pewne ryzyko przepełnienia, jeśli licznik podstawy czasu jest dość duży. Jeśli ktoś jest ciekawy, tutaj znajduje się link z wieloma dodatkowymi informacjami: https://stackoverflow.com/a/23378064/588476
W świetle tych informacji może bezpieczniej jest korzystać z funkcji Apple
CACurrentMediaTime
!mach_timebase_info
Przeprowadziłem również test porównawczy połączenia i na moim iPhonie 6 zajmuje to około 19ns, więc usunąłem (nie zabezpieczony wątkami) kod, który buforował dane wyjściowe tego połączenia.Należy być świadomym potencjalnego ryzyka przepełnienia w zależności od wyniku wywołania podstawy czasu. Podejrzewam (ale nie wiem), że może to być stała dla każdego modelu iPhone'a. na moim iPhonie 6 to było
125/3
.Zastosowanie rozwiązania
CACurrentMediaTime()
jest dość trywialne:źródło
mach_timebase_info()
zresetuje przekazywane wmach_timebase_info_data_t
celu{0,0}
przed ustawieniem go do rzeczywistych wartości, które mogą spowodować dzielenie przez zero, jeśli kod jest wywoływana z wielu wątków. Użyjdispatch_once()
zamiast tego (lubCACurrentMediaTime
który jest po prostu czasem mach przekonwertowanym na sekundy).Aby uzyskać dokładne pomiary czasu (takie jak GetTickCount), zapoznaj się również z mach_absolute_time oraz z pytaniami i odpowiedziami firmy Apple: http://developer.apple.com/qa/qa2004/qa1398.html .
źródło
użyj funkcji timeIntervalSince1970 klasy NSDate jak poniżej:
w zasadzie to właśnie używam do porównania różnicy w sekundach między 2 różnymi datami. sprawdź również ten link tutaj
źródło
Pozostałe odpowiedzi są poprawne (z zastrzeżeniem *). Dodaję tę odpowiedź, aby pokazać przykładowe użycie:
W konsoli debugera zobaczysz coś takiego:
* Uwaga: jak wspominali inni, używaj
NSDate
do obliczania czasu, który upłynął, tylko do celów dorywczych. Jednym z takich celów może być powszechne testowanie, prymitywne profilowanie, w którym chcesz po prostu uzyskać ogólne pojęcie o tym, jak długo trwa metoda.Istnieje ryzyko, że bieżące ustawienie zegara urządzenia może się zmienić w dowolnym momencie z powodu synchronizacji zegara sieciowego.
NSDate
Czas mógł więc w każdej chwili przeskoczyć do przodu lub do tyłu.źródło