Ich muss die zwischen zwei Ereignissen verstrichene Zeit ermitteln, z. B. das Erscheinen eines UIView und die erste Reaktion des Benutzers.
Wie kann ich es in Objective-C erreichen?
ios
objective-c
Ilya Suzdalnitski
quelle
quelle
fabs(...)
, um den absoluten Wert eines Floats zu erhalten. Z.B.NSTimeInterval timeInterval = fabs([start timeIntervalSinceNow]);
[NSDate date]
kann dies zu schwer zu verfolgenden Fehlern führen. Weitere Informationen finden Sie in dieser Antwort .Sie sollten sich nicht auf
[NSDate date]
Timing-Zwecke verlassen, da dies die verstrichene Zeit über- oder unterschätzen kann. Es gibt sogar Fälle, in denen Ihr Computer scheinbar eine Zeitreise unternimmt, da die verstrichene Zeit negativ ist! (ZB wenn sich die Uhr während des Timings rückwärts bewegte.)Laut Aria Haghighi in der Vorlesung "Advanced iOS Gesture Recognition" des Stanford iOS-Kurses Winter 2013 (34:00) sollten Sie diese verwenden,
CACurrentMediaTime()
wenn Sie ein genaues Zeitintervall benötigen.Ziel c:
Schnell:
Der Grund dafür ist, dass die
[NSDate date]
Synchronisierung auf dem Server zu "Zeitsynchronisierungsproblemen" führen kann, die zu sehr schwer zu verfolgenden Fehlern führen können.CACurrentMediaTime()
Andererseits ist dies eine Gerätezeit, die sich bei diesen Netzwerksynchronisierungen nicht ändert.Sie müssen das QuartzCore-Framework zu den Einstellungen Ihres Ziels hinzufügen .
quelle
[NSDate date]
innerhalb eines Abschlussblocks innerhalb eines Versandblocks wurde dieselbe "aktuelle" Zeit angezeigt, die[NSDate date]
unmittelbar vor der Ausführung gemeldet wurde, als der Punkt erreicht wurde, an dem meine Blöcke erstellt wurden.CACurrentMediaTime()
Dieses Problem wurde behoben.CACurrentMediaTime()
Ticken aufhört, wenn das Gerät in den Ruhezustand wechselt. Wenn Sie testen, während das Gerät von einem Computer getrennt ist, sperren Sie es und warten Sie ca. 10 Minuten. Sie werden feststellen, dassCACurrentMediaTime()
dies nicht mit der Wanduhrzeit Schritt hält.Verwenden Sie die
timeIntervalSinceDate
MethodeNSTimeInterval
ist nur eindouble
, definieren Sie inNSDate
wie folgt :quelle
Für alle, die hierher kommen und nach einer getTickCount () - Implementierung für iOS suchen, ist hier meine, nachdem sie verschiedene Quellen zusammengestellt haben.
Zuvor hatte ich einen Fehler in diesem Code (ich habe zuerst durch 1000000 geteilt), der eine Quantisierung der Ausgabe auf meinem iPhone 6 verursachte (möglicherweise war dies kein Problem auf dem iPhone 4 / etc oder ich habe es einfach nie bemerkt). Beachten Sie, dass, wenn diese Division nicht zuerst ausgeführt wird, ein gewisses Überlaufrisiko besteht, wenn der Zähler der Zeitbasis ziemlich groß ist. Wenn jemand neugierig ist, gibt es hier einen Link mit viel mehr Informationen: https://stackoverflow.com/a/23378064/588476
Angesichts dieser Informationen ist es möglicherweise sicherer, die Apple-Funktion zu verwenden
CACurrentMediaTime
!Ich habe den
mach_timebase_info
Anruf auch einem Benchmarking unterzogen und auf meinem iPhone 6 dauert es ungefähr 19 ns. Daher habe ich den (nicht threadsicheren) Code entfernt, der die Ausgabe dieses Anrufs zwischengespeichert hat.Beachten Sie das potenzielle Risiko eines Überlaufs in Abhängigkeit von der Ausgabe des Zeitbasisaufrufs. Ich vermute (aber weiß nicht), dass es eine Konstante für jedes iPhone-Modell sein könnte. auf meinem iPhone 6 war es
125/3
.Die Lösung
CACurrentMediaTime()
ist ziemlich trivial:quelle
mach_timebase_info()
setzt die Übergabe auf zurückmach_timebase_info_data_t
,{0,0}
bevor sie auf die tatsächlichen Werte gesetzt wird. Dies kann zu einer Division durch Null führen, wenn Code von mehreren Threads aufgerufen wird. Verwenden Siedispatch_once()
stattdessen (oderCACurrentMediaTime
dies ist nur die in Sekunden umgerechnete Mach-Zeit).Informationen zur genauen Zeitmessung (wie GetTickCount) finden Sie auch unter mach_absolute_time und in den Apple-Fragen und Antworten: http://developer.apple.com/qa/qa2004/qa1398.html .
quelle
Verwenden Sie die timeIntervalSince1970-Funktion der NSDate-Klasse wie folgt:
Im Grunde ist es das, was ich benutze, um den Unterschied in Sekunden zwischen 2 verschiedenen Daten zu vergleichen. Überprüfen Sie auch diesen Link hier
quelle
Die anderen Antworten sind richtig (mit einer Einschränkung *). Ich füge diese Antwort einfach hinzu, um eine Beispielverwendung zu zeigen:
Auf der Debugger-Konsole sehen Sie ungefähr Folgendes:
* Vorsichtsmaßnahme: Verwenden Sie
NSDate
, wie bereits erwähnt, die Berechnung der verstrichenen Zeit nur für gelegentliche Zwecke. Ein solcher Zweck könnte das allgemeine Testen sein, das grobe Profiling, bei dem Sie nur eine ungefähre Vorstellung davon haben möchten, wie lange eine Methode dauert.Das Risiko besteht darin, dass sich die aktuelle Zeiteinstellung des Geräts aufgrund der Synchronisierung der Netzwerkuhr jederzeit ändern kann. Die
NSDate
Zeit könnte also jederzeit vorwärts oder rückwärts springen.quelle