Gibt es eine einfache Möglichkeit, eine Zeit sehr genau zu bestimmen?
Ich muss einige Verzögerungen zwischen Methodenaufrufen berechnen. Insbesondere möchte ich die Geschwindigkeit des Bildlaufs in einer UIScrollView berechnen.
iphone
objective-c
cocoa-touch
uikit
Vielen Dank
quelle
quelle
Antworten:
NSDate
und dietimeIntervalSince*
Methoden gebenNSTimeInterval
ein Double mit einer Genauigkeit von weniger als einer Millisekunde zurück.NSTimeInterval
ist in Sekunden, aber es verwendet das Doppel, um Ihnen mehr Präzision zu geben.Um die Millisekunden-Zeitgenauigkeit zu berechnen, haben Sie folgende Möglichkeiten:
Dokumentation zu timeIntervalSinceNow .
Es gibt viele andere Möglichkeiten , um dieses Intervall zu berechnen verwenden
NSDate
, und ich würde in der Klasse Dokumentation empfehlen , sich fürNSDate
welche gefunden wird NSDate Klassenreferenz .quelle
NSDate
undmach_absolute_time()
auf ungefähr 30ms Niveau. 27 vs. 29, 36 vs. 39, 43 vs. 45.NSDate
war für mich einfacher zu verwenden und die Ergebnisse waren ähnlich genug, um sich nicht darum zu kümmern.mach_absolute_time()
kann verwendet werden, um genaue Messungen zu erhalten.Siehe http://developer.apple.com/qa/qa2004/qa1398.html
Ebenfalls erhältlich ist
CACurrentMediaTime()
, was im Wesentlichen dasselbe ist, jedoch mit einer benutzerfreundlicheren Oberfläche.quelle
CACurrentMediaTime()
diemach_absolute_time()
direkt in eine konvertiert werden kanndouble
.elapsedNano
ist vom TypNanoseconds
, der kein einfacher ganzzahliger Typ ist. Es ist ein Alias vonUnsignedWide
, bei dem es sich um eine Struktur mit zwei 32-Bit-Ganzzahlfeldern handelt. Sie könnenUnsignedWideToUInt64()
anstelle der Besetzung verwenden, wenn Sie es vorziehen.Bitte verwenden Sie nicht
NSDate
,CFAbsoluteTimeGetCurrent
oder diegettimeofday
verstrichene Zeit zu messen. Diese hängen alle auf dem Systemtakt, die ändern können jeder aufgrund vielen verschiedenen Gründen Zeit, wie zum Beispiel Netzwerk - Zeitsynchronisation (NTP) die Aktualisierung der Uhr (oft geschieht , um die Drift zu justieren), DST Anpassungen, Schaltsekunden, und so weiter.Dies bedeutet, dass Sie beim Messen Ihrer Download- oder Upload-Geschwindigkeit plötzliche Spitzen oder Abnahmen in Ihren Zahlen erhalten, die nicht mit dem korrelieren, was tatsächlich passiert ist. Ihre Leistungstests haben seltsame falsche Ausreißer. und Ihre manuellen Timer werden nach falscher Dauer ausgelöst. Die Zeit könnte sogar rückwärts gehen, und Sie erhalten negative Deltas, und Sie können mit unendlicher Rekursion oder totem Code enden (ja, ich habe beides getan).
Verwenden Sie
mach_absolute_time
. Es misst echte Sekunden seit dem Booten des Kernels. Es nimmt monoton zu (wird niemals rückwärts gehen) und wird von den Einstellungen für Datum und Uhrzeit nicht beeinflusst. Da es ein Problem ist, damit zu arbeiten, finden Sie hier einen einfachen Wrapper, der Ihnen Folgendes bietetNSTimeInterval
:quelle
CACurrentMediaTime()
QuartzCore?@import Darwin;
anstelle von#include <mach/mach_time.h>
CFAbsoluteTimeGetCurrent()
gibt die absolute Zeit alsdouble
Wert zurück, aber ich weiß nicht, wie genau sie ist - sie wird möglicherweise nur alle Dutzend Millisekunden aktualisiert, oder sie wird möglicherweise alle Mikrosekunden aktualisiert, ich weiß nicht.quelle
72.89674947369
Sekunden wäre ziemlich ungewöhnlich, wenn man alle anderen Werte berücksichtigt, die er sein könnte. ;)Ich würde NICHT verwenden,
mach_absolute_time()
da es eine Kombination aus Kernel und Prozessor für eine absolute Zeit mit Ticks abfragt (wahrscheinlich eine Verfügbarkeit).Was ich verwenden würde:
Diese Funktion wurde optimiert, um den Unterschied zwischen iOS- und OSX-Software und -Hardware zu korrigieren.
Etwas Geekier
Der Quotient einer Differenz in
mach_absolute_time()
undAFAbsoluteTimeGetCurrent()
liegt immer bei 24000011.154871Hier ist ein Protokoll meiner App:
Bitte beachten Sie, dass Endergebnisses Es ist ein Unterschied in
CFAbsoluteTimeGetCurrent()
‚squelle
mach_absolute_time()
einmach_timebase_info_data
und tat es dann(long double)((mach_absolute_time()*time_base.numer)/((1000*1000)*time_base.denom));
. Um die Mach-Zeitbasis zu erhalten, können Sie tun(void)mach_timebase_info(&your_timebase);
Verwendung:
Ausgabe:
quelle
NSDate
hängt von der Systemuhr ab, die jederzeit geändert werden kann, was möglicherweise zu falschen oder sogar negativen Zeitintervallen führt. Verwenden Siemach_absolute_time
stattdessen, um die korrekte verstrichene Zeit zu erhalten.mach_absolute_time
kann durch Neustarts des Geräts beeinträchtigt werden. Verwenden Sie stattdessen die Serverzeit.Außerdem
NSNumber
erfahren Sie hier, wie Sie ein mit der Unix-Epoche initialisiertes 64-Bit in Millisekunden berechnen , falls Sie es auf diese Weise in CoreData speichern möchten. Ich brauchte dies für meine App, die mit einem System interagiert, das Daten auf diese Weise speichert.quelle
Funktionen basierend auf
mach_absolute_time
sind gut für kurze Messungen.Bei langen Messungen ist es jedoch wichtig, dass sie nicht mehr ticken, während das Gerät schläft.
Es gibt eine Funktion, um Zeit seit dem Booten zu bekommen. Es hört im Schlaf nicht auf. Auch
gettimeofday
ist nicht monoton, aber in meinen Experimenten habe ich immer gesehen, dass sich die Startzeit ändert, wenn sich die Systemzeit ändert, also denke ich, dass es gut funktionieren sollte.Und seit iOS 10 und macOS 10.12 können wir CLOCK_MONOTONIC verwenden:
Etwas zusammenfassen:
Date.timeIntervalSinceReferenceDate
- ändert sich, wenn sich die Systemzeit ändert, nicht monotonCFAbsoluteTimeGetCurrent()
- nicht monoton, kann rückwärts gehenCACurrentMediaTime()
- hört auf zu ticken, wenn das Gerät schläfttimeSinceBoot()
- schläft nicht, ist aber möglicherweise nicht monotonCLOCK_MONOTONIC
- schläft nicht, monoton, wird seit iOS 10 unterstütztquelle
Ich weiß, dass dies eine alte ist, aber selbst ich bin wieder daran vorbeigekommen, also dachte ich, ich würde hier meine eigene Option einreichen.
Am besten schau dir meinen Blog-Beitrag dazu an: Timing der Dinge in Objective-C: Eine Stoppuhr
Grundsätzlich habe ich eine Klasse geschrieben, die auf sehr einfache Weise aufhört zu schauen, aber gekapselt ist, sodass Sie nur Folgendes tun müssen:
Und am Ende haben Sie:
im Protokoll ...
Schauen Sie sich meinen Beitrag noch einmal an oder laden Sie ihn hier herunter: MMStopwatch.zip
quelle
NSDate
hängt von der Systemuhr ab, die jederzeit geändert werden kann, was möglicherweise zu falschen oder sogar negativen Zeitintervallen führt. Verwenden Siemach_absolute_time
stattdessen, um die korrekte verstrichene Zeit zu erhalten.Sie können die aktuelle Zeit in Millisekunden seit dem 1. Januar 1970 mit einem NSDate abrufen:
quelle
Für diejenigen brauchen wir die Swift-Version der Antwort von @Jeff Thompson:
Ich hoffe das hilft dir.
quelle
NSDate
hängt von der Systemuhr ab, die jederzeit geändert werden kann, was möglicherweise zu falschen oder sogar negativen Zeitintervallen führt. Verwenden Siemach_absolute_time
stattdessen, um die korrekte verstrichene Zeit zu erhalten.