在Objective-C中花费时间

Ily*_*ski 150 objective-c ios

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

如何在Objective-C中实现它?

Can*_*der 262

NSDate *start = [NSDate date];
// do stuff...
NSTimeInterval timeInterval = [start timeIntervalSinceNow];
Run Code Online (Sandbox Code Playgroud)

timeInterval 是start和now之间的差异,以秒为单位,精确到亚毫秒级.

  • @NicolasZozol你可以使用`fabs(...)`来获得浮点数的绝对值.例如.`NSTimeInterval timeInterval = fabs([start timeIntervalSinceNow]);` (18认同)
  • 依靠"[NSDate date]"可能导致难以跟踪错误,请参阅[此答案](http://stackoverflow.com/a/17986909/35690)以获取更多信息. (10认同)
  • 所以如果我理解正确,这是一个负值 (6认同)
  • 似乎 timeInterval 的值为负数。 (2认同)

Sen*_*ful 223

您不应该依赖于[NSDate date]计时目的,因为它可能会超过或低于报告已用时间.甚至有些情况下,您的计算机似乎是时间旅行,因为经过的时间将是负面的!(例如,如果时钟在计时期间向后移动.)

根据Aria Haghighi在2013年冬季斯坦福iOS课程(34:00)的"高级iOS手势识别"讲座中的说法,CACurrentMediaTime()如果您需要准确的时间间隔,则应该使用.

Objective-C的:

#import <QuartzCore/QuartzCore.h>
Run Code Online (Sandbox Code Playgroud)
CFTimeInterval startTime = CACurrentMediaTime();
// perform some action
CFTimeInterval elapsedTime = CACurrentMediaTime() - startTime;
Run Code Online (Sandbox Code Playgroud)

迅速:

let startTime = CACurrentMediaTime()
// perform some action
let elapsedTime = CACurrentMediaTime() - startTime
Run Code Online (Sandbox Code Playgroud)

原因是[NSDate date]服务器上的同步,因此可能导致"时间同步打嗝",这可能导致非常难以跟踪的错误.CACurrentMediaTime()另一方面,设备时间不随这些网络同步而改变.

您将需要添加QuartzCore框架到目标的设置.

  • 请注意这一点.虽然我认为每个人都同意NSDate应该是你的第一选择,但这个建议解决了我的问题.在调度块中的完成块内调用"[NSDate date]"时,我在执行到创建块之前立即获得"[NSDate date]"报告的"当前"时间.`CACurrentMediaTime()`解决了这个问题. (16认同)
  • 请注意,当设备进入睡眠状态时,"CACurrentMediaTime()"会停止滴答声.如果您在断开计算机设备的情况下进行测试,请将其锁定,然后等待~10分钟,您会发现`CACurrentMediaTime()`无法跟上挂钟时间. (12认同)

Mar*_*eri 23

使用该timeIntervalSinceDate方法

NSTimeInterval secondsElapsed = [secondDate timeIntervalSinceDate:firstDate];
Run Code Online (Sandbox Code Playgroud)

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

typedef double NSTimeInterval;
Run Code Online (Sandbox Code Playgroud)


Way*_*oda 15

对于任何来到这里寻找iOS的getTickCount()实现的人来说,将各种来源放在一起之后,这是我的.

以前我在这段代码中有一个错误(我首先除以1000000),这导致iPhone 6上的输出量化(也许这不是iPhone 4 /等上的问题,或者我从未注意到它).请注意,如果不首先执行该除法,如果时基的分子非常大,则存在一些溢出的风险.如果有人好奇,可以在这里找到更多信息的链接: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;
}
Run Code Online (Sandbox Code Playgroud)

请注意潜在的溢出风险,具体取决于时基调用的输出.我怀疑(但不知道)它可能是每个iPhone型号的常量.在我的iPhone 6上它125/3.

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

uint64_t getTickCount(void)
{
    double ret = CACurrentMediaTime();
    return ret * 1000;
}
Run Code Online (Sandbox Code Playgroud)

  • 这不是线程安全的.`mach_timebase_info()`将把传入的`mach_timebase_info_data_t`重置为`{0,0}`,然后再将其设置为实际值,如果从多个线程调用代码,则可能导致除零.使用`dispatch_once()`代替(或'CACurrentMediaTime`,它只是马赫时间转换为秒). (2认同)

Jas*_*oco 8

对于percise时间测量(如GetTickCount),还可以查看mach_absolute_time和Apple问答:http://developer.apple.com/qa/qa2004/qa1398.html.


归档时间:

查看次数:

113466 次

最近记录:

6 年,10 月 前