在Objective-C中获得时间


Answers:


267
NSDate *start = [NSDate date];
// do stuff...
NSTimeInterval timeInterval = [start timeIntervalSinceNow];

timeInterval 是开始与现在之间的差(以秒为单位),精确到亚毫秒。


18
您可以使用@NicolasZozol fabs(...)获取浮点数的绝对值。例如。NSTimeInterval timeInterval = fabs([start timeIntervalSinceNow]);
所以就在

1
似乎timeInterval的值为负。
Jacky 2013年

如果您得到负值-乘以-1就表示您很好
PinkFloydRocks

10
依赖[NSDate date]可能导致难以跟踪的错误,请参阅此答案以获取更多信息。
有意义的2013年

@PinkFloydRocks-什么?负值将如何合法地出现?
Todd Lehman

228

您不应依赖[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框架到目标的设置。


17
请对此投票。尽管我认为每个人都可以同意NSDate应该是您的首选,但该建议解决了我的问题。当[NSDate date]在调度块内的完成块内调用时,我得到的“当前”时间与[NSDate date]执行达到创建块的时间点之前报告的时间相同。CACurrentMediaTime()解决了这个问题。
n00neimp0rtant

我们如何使用elapsedTime进行类似mm:ss的显示?
Cyber​​Mew

@Cyber​​Mew:那是一个单独的问题。请参阅如何在iPhone上将NSTimeInterval分解为年,月,日,小时,分钟和秒?对于一些解决方案。
有意义的

12
请注意,CACurrentMediaTime()当设备进入睡眠状态时,它会停止滴答。如果在断开设备与计算机的连接的状态下进行测试,请锁定该设备,然后等待约10分钟,您将发现它CACurrentMediaTime()不符合挂钟时间。
russbishop 2015年

添加和导入#import <QuartzCore / QuartzCore.h>
steveen zoleko

23

使用timeIntervalSinceDate方法

NSTimeInterval secondsElapsed = [secondDate timeIntervalSinceDate:firstDate];

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

typedef double NSTimeInterval;

15

对于来到这里寻找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调用上存在冗余(无效)吗?
西蒙·蒂尔森

@SimonTillson是个很好的问题-必须关闭警告,或者我从其他地方复制了它,只是没有注意到删除它。我不记得了
韦恩·浦田

2
这不是线程安全的。mach_timebase_info()将复位传入mach_timebase_info_data_t{0,0}它设置为实际值,这会导致被零分裂如果代码是从多个线程调用之前。使用dispatch_once()代替(或CACurrentMediaTime仅将马赫时间转换为秒)。
wonder.mice,

感谢@ wonder.mice,我更新了我的答案(也发现了一个有关量化的问题,我怪我
还不到


4

使用NSDate类的timeIntervalSince1970函数,如下所示:

double start = [startDate timeIntervalSince1970];
double end = [endDate timeIntervalSince1970];
double difference = end - start;

基本上,这就是我用来比较2个不同日期之间以秒为单位的差异的原因。在这里也检查此链接


0

其他答案是正确的(警告*)。我添加此答案只是为了显示示例用法:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.