我怎样才能得到一个精确的时间,例如在Objective-C中以毫秒为单位?
有一个简单的方法来得到一个非常精确的时间?
我需要计算方法调用之间的一些延迟。 更具体地说,我想计算一个UIScrollView的滚动速度。
NSDate
和timeIntervalSince*
方法将返回一个NSTimeInterval
,它是一个具有亚毫秒精度的双精度值。 NSTimeInterval
是在几秒钟内,但它使用双精度给你更大的精度。
为了计算毫秒的时间精度,你可以这样做:
// Get a current time for where you want to start measuring from NSDate *date = [NSDate date]; // do work... // Find elapsed time and convert to milliseconds // Use (-) modifier to conversion since receiver is earlier than now double timePassed_ms = [date timeIntervalSinceNow] * -1000.0;
timeIntervalSinceNow上的文档 。
有很多其他的方法来计算这个间隔使用NSDate
,我build议看看在NSDate类参考NSDate的类文档 。
mach_absolute_time()
可用于获取精确的测量结果。
请参阅http://developer.apple.com/qa/qa2004/qa1398.html
也可以使用CACurrentMediaTime()
,它基本上是一样的,但是有一个更易于使用的界面。
请不要使用NSDate
, CFAbsoluteTimeGetCurrent
或gettimeofday
来测量已用时间。 这些都取决于系统时钟,由于许多不同的原因,例如networking时间同步(NTP)更新时钟(经常发生漂移调整),DST调整,闰秒等等,可以随时更改系统时钟。
这意味着,如果你正在测量你的下载或上传速度,你会得到突然的高峰或下降的数字,与实际发生的事情不相关; 你的性能testing会有奇怪的不正确的离群值; 而您的手动定时器会在不正确的持续时间后触发。 时间甚至可能会倒退,最终会产生负面的变化,最终会产生无限的recursion或死代码(是的,我已经完成了这两个)。
使用mach_absolute_time
。 它测量自内核启动以来的真实秒数。 它单调递增(永远不会倒退),不受date和时间设置的影响。 由于这是一个痛苦的工作,这里有一个简单的包装,给你NSTimeInterval
s:
// LBClock.h @interface LBClock : NSObject + (instancetype)sharedClock; // since device boot or something. Monotonically increasing, unaffected by date and time settings - (NSTimeInterval)absoluteTime; - (NSTimeInterval)machAbsoluteToTimeInterval:(uint64_t)machAbsolute; @end // LBClock.m #include <mach/mach.h> #include <mach/mach_time.h> @implementation LBClock { mach_timebase_info_data_t _clock_timebase; } + (instancetype)sharedClock { static LBClock *g; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ g = [LBClock new]; }); return g; } - (id)init { if(!(self = [super init])) return nil; mach_timebase_info(&_clock_timebase); return self; } - (NSTimeInterval)machAbsoluteToTimeInterval:(uint64_t)machAbsolute { uint64_t nanos = (machAbsolute * _clock_timebase.numer) / _clock_timebase.denom; return nanos/1.0e9; } - (NSTimeInterval)absoluteTime { uint64_t machtime = mach_absolute_time(); return [self machAbsoluteToTimeInterval:machtime]; } @end
CFAbsoluteTimeGetCurrent()
将绝对时间作为double
值返回,但我不知道它的精度是多less – 它可能只会每十几毫秒更新一次,也可能每微秒更新一次,我不知道。
我不会使用mach_absolute_time()
因为它使用ticks(可能是正常运行时间)查询内核和处理器的绝对时间组合。
我会用什么:
CFAbsoluteTimeGetCurrent();
此function经过优化,以纠正iOS和OSX软件和硬件的差异。
东西很热心
mach_absolute_time()
和AFAbsoluteTimeGetCurrent()
差的商总是在24000011.154871附近
这是我的应用程序的日志:
请注意,最终结果时间是CFAbsoluteTimeGetCurrent()
的差异
2012-03-19 21:46:35.609 Rest Counter[3776:707] First Time: 353900795.609040 2012-03-19 21:46:36.360 Rest Counter[3776:707] Second Time: 353900796.360177 2012-03-19 21:46:36.361 Rest Counter[3776:707] Final Result Time (difference): 0.751137 2012-03-19 21:46:36.363 Rest Counter[3776:707] Mach absolute time: 18027372 2012-03-19 21:46:36.365 Rest Counter[3776:707] Mach absolute time/final time: 24000113.153295 2012-03-19 21:46:36.367 Rest Counter[3776:707] ----------------------------------------------------- 2012-03-19 21:46:43.074 Rest Counter[3776:707] First Time: 353900803.074637 2012-03-19 21:46:43.170 Rest Counter[3776:707] Second Time: 353900803.170256 2012-03-19 21:46:43.172 Rest Counter[3776:707] Final Result Time (difference): 0.095619 2012-03-19 21:46:43.173 Rest Counter[3776:707] Mach absolute time: 2294833 2012-03-19 21:46:43.175 Rest Counter[3776:707] Mach absolute time/final time: 23999753.727777 2012-03-19 21:46:43.177 Rest Counter[3776:707] ----------------------------------------------------- 2012-03-19 21:46:46.499 Rest Counter[3776:707] First Time: 353900806.499199 2012-03-19 21:46:55.017 Rest Counter[3776:707] Second Time: 353900815.016985 2012-03-19 21:46:55.018 Rest Counter[3776:707] Final Result Time (difference): 8.517786 2012-03-19 21:46:55.020 Rest Counter[3776:707] Mach absolute time: 204426836 2012-03-19 21:46:55.022 Rest Counter[3776:707] Mach absolute time/final time: 23999996.639500 2012-03-19 21:46:55.024 Rest Counter[3776:707] -----------------------------------------------------
#define CTTimeStart() NSDate * __date = [NSDate date] #define CTTimeEnd(MSG) NSLog(MSG " %g",[__date timeIntervalSinceNow]*-1)
用法:
CTTimeStart(); ... CTTimeEnd(@"that was a long time:");
输出:
2013-08-23 15:34:39.558 App-Dev[21229:907] that was a long time: .0023
另外,下面是如何计算一个64位的NSNumber
,以毫秒为单位初始化Unix纪元,以防你如何将它存储在CoreData中。 我需要这个与我的应用程序相互作用的系统,这样的存储date。
+ (NSNumber*) longUnixEpoch { return [NSNumber numberWithLongLong:[[NSDate date] timeIntervalSince1970] * 1000]; }
我知道这是一个古老的,但即使我发现自己再次徘徊,所以我想我会在这里提交自己的select。
最好的办法是查看我的博客文章: Objective-C中的定时事物:秒表
基本上,我写了一个类,停止看一个非常基本的方式,但封装,所以你只需要做到以下几点:
[MMStopwatchARC start:@"My Timer"]; // your work here ... [MMStopwatchARC stop:@"My Timer"];
最后你会得到:
MyApp[4090:15203] -> Stopwatch: [My Timer] runtime: [0.029]
在日志中…
再次,看看我的post多一点或在这里下载: MMStopwatch.zip
对于那些我们需要@Jeff Thompson的Swift版答案的人:
// Get a current time for where you want to start measuring from var date = NSDate() // do work... // Find elapsed time and convert to milliseconds // Use (-) modifier to conversion since receiver is earlier than now var timePassed_ms: Double = date.timeIntervalSinceNow * -1000.0
我希望这可以帮助你。
您可以使用NSDate从1970年1月1日起以毫秒为单位获取当前时间:
- (double)currentTimeInMilliseconds { NSDate *date = [NSDate date]; return [date timeIntervalSince1970]*1000; }