在 Objective-C 中获取消耗的时间

我需要得到两个事件之间的时间间隔,例如,UIView 的出现和用户的第一反应。

如何在 Objective-C 中实现它?

121410 次浏览
NSDate *start = [NSDate date];
// do stuff...
NSTimeInterval timeInterval = [start timeIntervalSinceNow];

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方法

NSTimeInterval secondsElapsed = [secondDate timeIntervalSinceDate:firstDate];

NSTimeInterval只是一个 double,在 NSDate中定义如下:

typedef double NSTimeInterval;

对于那些来这里寻找用于 iOS 的 getTickCount ()实现的人来说,这里是我将各种源代码放在一起后得到的。

之前我在这段代码中有一个 bug (我先除以1000000) ,导致我的 iPhone 6的输出量化(也许这在 iPhone 4/etc 上不是一个问题,或者我只是从来没有注意到它)。请注意,如果不首先执行该除法,那么如果时间基的分子非常大,则存在溢出的风险。如果有人感兴趣的话,这里有一个更多信息的链接: https://stackoverflow.com/a/23378064/588476

根据这些信息,也许使用苹果的功能 CACurrentMediaTime会更安全!

我还对 mach_timebase_info调用进行了基准测试,它在我的 iPhone6上大约需要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。在我的 iPhone6上是 125/3

使用 CACurrentMediaTime()的解决方案非常简单:

uint64_t getTickCount(void)
{
double ret = CACurrentMediaTime();
return ret * 1000;
}

出于计时的目的,您不应该依赖于 [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 也可以工作。

其他的答案都是正确的(附带一个警告 *)。我添加这个答案只是为了展示一个用法示例:

- (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时间可以随时向前或向后跳跃。