我需要得到两个事件之间的时间间隔,例如,UIView 的出现和用户的第一反应。
如何在 Objective-C 中实现它?
NSDate *start = [NSDate date]; // do stuff... NSTimeInterval timeInterval = [start timeIntervalSinceNow];
timeInterval是开始和现在之间的差异,以秒为单位,精度为毫秒以下。
timeInterval
使用 NSDate 类的 timeIntervalSince1970函数,如下所示:
double start = [startDate timeIntervalSince1970]; double end = [endDate timeIntervalSince1970]; double difference = end - start;
基本上,这就是我用来比较两个不同日期之间秒差的东西。也检查这个链接 给你
对于精确时间测量(如 GetTickCount) ,还可以查看 mach _ Absol_ time 和这个 Apple Q & A: http://developer.apple.com/qa/qa2004/qa1398.html。
使用 timeIntervalSinceDate方法
timeIntervalSinceDate
NSTimeInterval secondsElapsed = [secondDate timeIntervalSinceDate:firstDate];
NSTimeInterval只是一个 double,在 NSDate中定义如下:
NSTimeInterval
double
NSDate
typedef double NSTimeInterval;
对于那些来这里寻找用于 iOS 的 getTickCount ()实现的人来说,这里是我将各种源代码放在一起后得到的。
之前我在这段代码中有一个 bug (我先除以1000000) ,导致我的 iPhone 6的输出量化(也许这在 iPhone 4/etc 上不是一个问题,或者我只是从来没有注意到它)。请注意,如果不首先执行该除法,那么如果时间基的分子非常大,则存在溢出的风险。如果有人感兴趣的话,这里有一个更多信息的链接: https://stackoverflow.com/a/23378064/588476
根据这些信息,也许使用苹果的功能 CACurrentMediaTime会更安全!
CACurrentMediaTime
我还对 mach_timebase_info调用进行了基准测试,它在我的 iPhone6上大约需要19ns,所以我删除了缓存该调用输出的(不是线程安全的)代码。
mach_timebase_info
#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。在我的 iPhone6上是 125/3。
125/3
使用 CACurrentMediaTime()的解决方案非常简单:
CACurrentMediaTime()
uint64_t getTickCount(void) { double ret = CACurrentMediaTime(); return ret * 1000; }
出于计时的目的,您不应该依赖于 [NSDate date],因为它可能会过多或过少报告所花费的时间。甚至有些情况下,你的计算机似乎会时间旅行,因为所经过的时间将是负数!(例如,如果时钟在计时过程中向后移动。)
[NSDate date]
根据 Aria Haghighi 在 2013年冬季斯坦福 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]在服务器上同步,所以它可能导致“时间同步打嗝”,这可能导致非常难以跟踪的错误。另一方面,CACurrentMediaTime()是一个不随网络同步而改变的设备时间。
您将需要 加的 QuartzCore 框架到您的目标的设置。
注意: 还有其他类似于 clock_gettime_nsec_np的 API 也可以工作。
clock_gettime_nsec_np
其他的答案都是正确的(附带一个警告 *)。我添加这个答案只是为了展示一个用法示例:
- (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时间可以随时向前或向后跳跃。