Adakah cara mudah untuk mendapatkan waktu dengan sangat tepat?
Saya perlu menghitung beberapa penundaan antara panggilan metode. Lebih khusus lagi, saya ingin menghitung kecepatan scrolling di UIScrollView.
iphone
objective-c
cocoa-touch
uikit
Terima kasih
sumber
sumber
Jawaban:
NSDate
dantimeIntervalSince*
metode akan mengembalikanNSTimeInterval
nilai ganda dengan akurasi sub-milidetik.NSTimeInterval
dalam hitungan detik, tapi menggunakan ganda untuk memberi Anda presisi yang lebih baik.Untuk menghitung akurasi waktu milidetik, Anda dapat melakukan:
Dokumentasi tentang timeIntervalSinceNow .
Ada banyak cara lain untuk menghitung interval ini menggunakan
NSDate
, dan saya akan merekomendasikan melihat dokumentasi kelasNSDate
yang ditemukan di Referensi Kelas NSDate .sumber
NSDate
danmach_absolute_time()
pada level sekitar 30ms. 27 vs. 29, 36 vs. 39, 43 vs. 45.NSDate
lebih mudah digunakan bagi saya dan hasilnya cukup mirip untuk tidak peduli.mach_absolute_time()
dapat digunakan untuk mendapatkan pengukuran yang tepat.Lihat http://developer.apple.com/qa/qa2004/qa1398.html
Juga tersedia
CACurrentMediaTime()
, yang pada dasarnya sama tetapi dengan antarmuka yang lebih mudah digunakan.(Catatan: Jawaban ini ditulis pada tahun 2009. Lihat jawaban Pavel Alexeev untuk
clock_gettime()
antarmuka POSIX yang lebih sederhana yang tersedia di versi macOS dan iOS yang lebih baru.)sumber
CACurrentMediaTime()
, yangmach_absolute_time()
langsung diubah menjadi filedouble
.elapsedNano
adalah tipeNanoseconds
, yang bukan tipe integer biasa. Ini adalah alias dariUnsignedWide
, yang merupakan struct dengan dua bidang integer 32-bit. Anda dapat menggunakanUnsignedWideToUInt64()
sebagai pengganti cast jika mau.Jangan gunakan
NSDate
,CFAbsoluteTimeGetCurrent
ataugettimeofday
untuk mengukur waktu berlalu. Ini semua bergantung pada jam sistem, yang dapat berubah kapan saja karena berbagai alasan, seperti sinkronisasi waktu jaringan (NTP) memperbarui jam (sering terjadi untuk menyesuaikan penyimpangan), penyesuaian DST, detik kabisat, dan sebagainya.Ini berarti bahwa jika Anda mengukur kecepatan unduh atau unggah, Anda akan mendapatkan lonjakan atau penurunan tiba-tiba pada angka Anda yang tidak berkorelasi dengan apa yang sebenarnya terjadi; tes kinerja Anda akan memiliki pencilan aneh yang salah; dan timer manual Anda akan terpicu setelah durasi yang salah. Waktu bahkan mungkin mundur, dan Anda berakhir dengan delta negatif, dan Anda bisa berakhir dengan rekursi tak terbatas atau kode mati (ya, saya telah melakukan keduanya).
Gunakan
mach_absolute_time
. Ini mengukur detik nyata sejak kernel di-boot. Ini meningkat secara monoton (tidak akan pernah mundur), dan tidak terpengaruh oleh pengaturan tanggal dan waktu. Karena merepotkan untuk dikerjakan, berikut bungkus sederhana yang memberi AndaNSTimeInterval
:sumber
CACurrentMediaTime()
QuartzCore?@import Darwin;
bukannya#include <mach/mach_time.h>
CFAbsoluteTimeGetCurrent()
mengembalikan waktu absolut sebagai sebuahdouble
nilai, tetapi saya tidak tahu apa ketepatannya - mungkin hanya memperbarui setiap lusin milidetik, atau mungkin memperbarui setiap mikrodetik, saya tidak tahu.sumber
72.89674947369
detik akan sangat tidak umum, mengingat semua nilai lain yang mungkin terjadi. ;)Saya TIDAK akan menggunakan
mach_absolute_time()
karena menanyakan kombinasi kernel dan prosesor untuk waktu absolut menggunakan kutu (mungkin uptime).Apa yang akan saya gunakan:
Fungsi ini dioptimalkan untuk memperbaiki perbedaan pada perangkat lunak dan perangkat keras iOS dan OSX.
Sesuatu yang lebih Geekier
Hasil bagi dari selisih
mach_absolute_time()
danAFAbsoluteTimeGetCurrent()
selalu sekitar 24000011.154871Ini adalah log aplikasi saya:
Harap dicatat bahwa waktu hasil akhir perbedaan di
CFAbsoluteTimeGetCurrent()
'ssumber
mach_absolute_time()
denganmach_timebase_info_data
dan kemudian melakukannya(long double)((mach_absolute_time()*time_base.numer)/((1000*1000)*time_base.denom));
. Untuk mendapatkan basis waktu mach, Anda dapat melakukannya(void)mach_timebase_info(&your_timebase);
Pemakaian:
Keluaran:
sumber
NSDate
bergantung pada jam sistem yang dapat diubah kapan saja, berpotensi menghasilkan interval waktu yang salah atau bahkan negatif. Gunakanmach_absolute_time
sebagai gantinya untuk mendapatkan waktu berlalu yang benar.mach_absolute_time
dapat terpengaruh oleh reboot perangkat. Gunakan waktu server sebagai gantinya.Selain itu, berikut adalah cara menghitung 64-bit yang
NSNumber
diinisialisasi dengan epoch Unix dalam milidetik, jika Anda ingin menyimpannya di CoreData. Saya membutuhkan ini untuk aplikasi saya yang berinteraksi dengan sistem yang menyimpan tanggal dengan cara ini.sumber
Fungsi berdasarkan
mach_absolute_time
bagus untuk pengukuran singkat.Namun untuk pengukuran yang lama, peringatan penting adalah bahwa mereka berhenti berdetak saat perangkat sedang tidur.
Ada fungsi untuk mendapatkan waktu sejak boot. Itu tidak berhenti saat tidur. Juga,
gettimeofday
ini tidak monotonik, tetapi dalam percobaan saya, saya selalu melihat bahwa waktu boot berubah ketika waktu sistem berubah, jadi saya pikir itu akan bekerja dengan baik.Dan karena iOS 10 dan macOS 10.12 kita dapat menggunakan CLOCK_MONOTONIC:
Singkatnya:
Date.timeIntervalSinceReferenceDate
- berubah ketika waktu sistem berubah, tidak monotonikCFAbsoluteTimeGetCurrent()
- tidak monotonik, mungkin mundurCACurrentMediaTime()
- berhenti berdetak saat perangkat tidurtimeSinceBoot()
- tidak tidur, tapi mungkin tidak monotonikCLOCK_MONOTONIC
- tidak tidur, monoton, didukung sejak iOS 10sumber
Saya tahu ini adalah yang lama tetapi bahkan saya mendapati diri saya melewatinya lagi, jadi saya pikir saya akan mengirimkan pilihan saya sendiri di sini.
Taruhan terbaik adalah memeriksa posting blog saya tentang ini : Pengaturan waktu di Objective-C: Sebuah stopwatch
Pada dasarnya, saya menulis kelas yang berhenti menonton dengan cara yang sangat dasar tetapi dikemas sehingga Anda hanya perlu melakukan hal berikut:
Dan Anda berakhir dengan:
di log ...
Sekali lagi, periksa posting saya untuk lebih banyak atau unduh di sini: MMStopwatch.zip
sumber
NSDate
bergantung pada jam sistem yang dapat diubah kapan saja, berpotensi menghasilkan interval waktu yang salah atau bahkan negatif. Gunakanmach_absolute_time
sebagai gantinya untuk mendapatkan waktu berlalu yang benar.Anda bisa mendapatkan waktu saat ini dalam milidetik sejak 1 Januari 1970 menggunakan NSDate:
sumber
Bagi mereka, kami membutuhkan versi Swift dari jawaban @Jeff Thompson:
Saya harap ini membantu Anda.
sumber
NSDate
tergantung pada jam sistem yang dapat diubah kapan saja, berpotensi menghasilkan interval waktu yang salah atau bahkan negatif. Menggunakanmach_absolute_time
sebagai gantinya untuk mendapatkan waktu berlalu yang benar.