我需要获取两个事件之间经过的时间,例如,UIView的外观和用户的第一反应。
如何在Objective-C中实现?
我需要获取两个事件之间经过的时间,例如,UIView的外观和用户的第一反应。
如何在Objective-C中实现?
Answers:
NSDate *start = [NSDate date];
// do stuff...
NSTimeInterval timeInterval = [start timeIntervalSinceNow];
timeInterval
是开始与现在之间的差(以秒为单位),精确到亚毫秒。
您不应依赖[NSDate date]
计时,因为它可能会高估或低估经过的时间。甚至在某些情况下,由于经过的时间为负,您的计算机似乎也会经过时间旅行!(例如,如果时钟在计时期间向后移动。)
根据Aria Haghighi在2013年冬季Stanford iOS课程(34:00)的“高级iOS手势识别”讲座中所说,CACurrentMediaTime()
如果需要准确的时间间隔,则应该使用。
目标C:
#import <QuartzCore/QuartzCore.h>
CFTimeInterval startTime = CACurrentMediaTime();
// perform some action
CFTimeInterval elapsedTime = CACurrentMediaTime() - startTime;
迅速:
let startTime = CACurrentMediaTime()
// perform some action
let elapsedTime = CACurrentMediaTime() - startTime
原因是[NSDate date]
服务器上的同步,因此可能导致“时间同步打ic”,这可能导致很难跟踪的错误。CACurrentMediaTime()
另一方面,设备时间不会随着这些网络同步而改变。
您将需要添加的QuartzCore框架到目标的设置。
[NSDate date]
在调度块内的完成块内调用时,我得到的“当前”时间与[NSDate date]
执行达到创建块的时间点之前报告的时间相同。CACurrentMediaTime()
解决了这个问题。
CACurrentMediaTime()
当设备进入睡眠状态时,它会停止滴答。如果在断开设备与计算机的连接的状态下进行测试,请锁定该设备,然后等待约10分钟,您将发现它CACurrentMediaTime()
不符合挂钟时间。
使用timeIntervalSinceDate
方法
NSTimeInterval secondsElapsed = [secondDate timeIntervalSinceDate:firstDate];
NSTimeInterval
只是一个double
,定义NSDate
如下:
typedef double NSTimeInterval;
对于来到这里寻找iOS的getTickCount()实现的任何人来说,这都是将各种资源放在一起后得到的。
以前,我在此代码中有一个错误(我先除以1000000),这导致我的iPhone 6上的输出发生了一些量化(也许这在iPhone 4 / etc上不是问题,或者我只是从未注意到)。请注意,如果时基的分子很大,则不先执行该除法操作就有溢出的风险。如果有人好奇,可以在这里找到更多信息的链接:https : //stackoverflow.com/a/23378064/588476
根据这些信息,使用Apple的功能也许更安全CACurrentMediaTime
!
我还对该mach_timebase_info
调用进行了基准测试,并且在我的iPhone 6上花费了大约19ns的时间,因此我删除了缓存该调用输出的(不是线程安全的)代码。
#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;
}
请注意时基调用的输出,潜在的溢出风险。我怀疑(但不知道)每种型号的iPhone可能都是一个常数。在我的iPhone 6上是125/3
。
使用的解决方案CACurrentMediaTime()
很简单:
uint64_t getTickCount(void)
{
double ret = CACurrentMediaTime();
return ret * 1000;
}
mach_timebase_info()
将复位传入mach_timebase_info_data_t
到{0,0}
它设置为实际值,这会导致被零分裂如果代码是从多个线程调用之前。使用dispatch_once()
代替(或CACurrentMediaTime
仅将马赫时间转换为秒)。
对于精确的时间测量(例如GetTickCount),还请查看mach_absolute_time和此Apple问题与解答:http : //developer.apple.com/qa/qa2004/qa1398.html。
其他答案是正确的(警告*)。我添加此答案只是为了显示示例用法:
- (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.
}
在调试器控制台上,您将看到以下内容:
DEBUG Method '-[XMAppDelegate getYourAffairsInOrder]' ran. Elapsed: 0.033827 seconds.
*注意:如其他人所述,NSDate
仅用于休闲目的用于计算经过时间。这样的目的之一可能是常规测试,粗略分析,您只想大致了解一种方法花费了多长时间。
风险是由于网络时钟同步,设备的时钟的当前时间设置随时可能更改。因此,NSDate
时间随时可能向前或向后跳跃。
fabs(...)
获取浮点数的绝对值。例如。NSTimeInterval timeInterval = fabs([start timeIntervalSinceNow]);