İki olay arasında geçen süreyi almam gerekiyor, örneğin bir UIView görünümü ve kullanıcının ilk tepkisi.
Objective-C ile nasıl başarabilirim?
İki olay arasında geçen süreyi almam gerekiyor, örneğin bir UIView görünümü ve kullanıcının ilk tepkisi.
Objective-C ile nasıl başarabilirim?
Yanıtlar:
NSDate *start = [NSDate date];
// do stuff...
NSTimeInterval timeInterval = [start timeIntervalSinceNow];
timeInterval
milisaniye altı hassasiyetle başlangıç ve şimdi arasındaki farkın saniye cinsinden farkıdır.
[NSDate date]
Geçen zamanı gereğinden fazla veya az rapor edebileceğinden, zamanlama amaçları için güvenmemelisiniz . Hatta geçen zaman negatif olacağından bilgisayarınızın görünüşte zaman yolculuğu olacağı durumlar bile var! (Örneğin, zamanlama sırasında saat geriye doğru hareket ederse.)
Winter 2013 Stanford iOS kursunun (34:00) "Gelişmiş iOS Hareket Tanıma" dersindeki Aria Haghighi'ye göre, CACurrentMediaTime()
doğru bir zaman aralığına ihtiyacınız varsa kullanmalısınız .
Objective-C:
#import <QuartzCore/QuartzCore.h>
CFTimeInterval startTime = CACurrentMediaTime();
// perform some action
CFTimeInterval elapsedTime = CACurrentMediaTime() - startTime;
Swift:
let startTime = CACurrentMediaTime()
// perform some action
let elapsedTime = CACurrentMediaTime() - startTime
Bunun nedeni [NSDate date]
sunucuda senkronize edilmesidir, bu nedenle izlenmesi çok zor hatalara yol açabilecek "zaman senkronizasyonu hıçkırıklarına" yol açabilir. CACurrentMediaTime()
diğer yandan, bu ağ senkronizasyonlarıyla değişmeyen bir cihaz süresidir.
Sen gerekecektir eklemek QuartzCore çerçevesini Hedefinizin ayarlarına.
[NSDate date]
dağıtım bloğu içindeki bir tamamlama bloğunu çağırırken , [NSDate date]
yürütme bloklarımın oluşturulduğu noktaya gelmeden hemen önce bildirilen aynı "şimdiki" zamanı alıyordum . CACurrentMediaTime()
bu sorunu çözdü.
CACurrentMediaTime()
cihaz uyku girdiğinde geçiyor durur. Cihazın bilgisayar bağlantısı kesilmiş durumdayken test ederseniz, kilitleyin, sonra CACurrentMediaTime()
duvar saatine uymadığını ~ 10 dakika bekleyin .
timeIntervalSinceDate
Yöntemi kullanın
NSTimeInterval secondsElapsed = [secondDate timeIntervalSinceDate:firstDate];
NSTimeInterval
sadece bir double
, şöyle tanımlayın NSDate
:
typedef double NSTimeInterval;
Buraya iOS için getTickCount () uygulaması arayan herkes için, çeşitli kaynakları bir araya getirdikten sonra benimdir.
Daha önce bu kodda bir hata vardı (ilk önce 1000000'e böldüm) ki bu benim iPhone 6'da çıkışın bir miktar miktarına neden oldu (belki de bu iPhone 4 / etc'de bir sorun değildi ya da hiç fark etmedim). İlk önce bu bölümü gerçekleştirmeyerek, zaman tabanının payı oldukça büyükse taşma riski olduğunu unutmayın. Merak eden biri varsa, burada daha fazla bilgi içeren bir bağlantı var: https://stackoverflow.com/a/23378064/588476
Bu bilgiler ışığında belki Apple'ın işlevini kullanmak daha güvenlidir CACurrentMediaTime
!
Ayrıca mach_timebase_info
aramayı kıyasladım ve iPhone 6'ımda yaklaşık 19ns sürüyor, bu yüzden bu aramanın çıkışını önbelleğe alan (threadsafe değil) kodunu kaldırdım.
#include <mach/mach.h>
#include <mach/mach_time.h>
uint64_t getTickCount(void)
{
mach_timebase_info_data_t sTimebaseInfo;
uint64_t machTime = mach_absolute_time();
// Convert to milliseconds
mach_timebase_info(&sTimebaseInfo);
machTime *= sTimebaseInfo.numer;
machTime /= sTimebaseInfo.denom;
machTime /= 1000000; // convert from nanoseconds to milliseconds
return machTime;
}
Zaman tabanı çağrısının çıkışına bağlı olarak olası taşma riskinin farkında olun. İPhone'un her modeli için sabit olabileceğinden şüpheleniyorum (ama bilmiyorum). iPhone 6'mda öyleydi 125/3
.
Kullanarak çözüm CACurrentMediaTime()
oldukça önemsiz:
uint64_t getTickCount(void)
{
double ret = CACurrentMediaTime();
return ret * 1000;
}
mach_timebase_info()
geçirildi, tekrar ayarlanır mach_timebase_info_data_t
için {0,0}
kod birden çok iş parçacığı denir eğer sıfıra bölme neden olabilir gerçek değerleri, bunu ayarlamadan önce. dispatch_once()
Bunun yerine kullanın (veya CACurrentMediaTime
yalnızca saniyeye dönüştürülen mach süresi).
Öldürme süresi ölçümleri için (GetTickCount gibi), mach_absolute_time ve şu Apple Q&A'ya da göz atın: http://developer.apple.com/qa/qa2004/qa1398.html .
NSDate sınıfının timeIntervalSince1970 işlevini aşağıdaki gibi kullanın:
double start = [startDate timeIntervalSince1970];
double end = [endDate timeIntervalSince1970];
double difference = end - start;
temelde, ben 2 farklı tarih arasındaki saniye farkı karşılaştırmak için kullandığım budur. ayrıca bu bağlantıyı buradan kontrol edin
Diğer cevaplar doğrudur (bir uyarı ile *). Bu cevabı basitçe örnek bir kullanım göstermek için ekliyorum:
- (void)getYourAffairsInOrder
{
NSDate* methodStart = [NSDate date]; // Capture start time.
// … Do some work …
NSLog(@"DEBUG Method %s ran. Elapsed: %f seconds.", __func__, -([methodStart timeIntervalSinceNow])); // Calculate and report elapsed time.
}
Hata ayıklayıcı konsolunda şöyle bir şey görürsünüz:
DEBUG Method '-[XMAppDelegate getYourAffairsInOrder]' ran. Elapsed: 0.033827 seconds.
* Uyarı: Diğerleri de belirtildiği gibi, NSDate
geçen zamanı sadece gündelik amaçlar için hesaplamak için kullanın . Böyle bir amaç, bir yöntemin ne kadar sürdüğü hakkında kabaca bir fikir edinmek istediğiniz ortak testler, ham profil oluşturma olabilir.
Risk, ağ saati senkronizasyonu nedeniyle cihazın saatinin geçerli saat ayarının her an değişebilmesidir. Böylece NSDate
zaman her an ileri veya geri atlayabilir.
fabs(...)
bir şamandıranın mutlak değerini elde etmek için kullanabilirsiniz . Örneğin.NSTimeInterval timeInterval = fabs([start timeIntervalSinceNow]);