为了账号安全,请及时绑定邮箱和手机立即绑定

今天看到一道很有意思的面试题,想了半天也不得其解,想上来问问大家。

今天看到一道很有意思的面试题,想了半天也不得其解,想上来问问大家。

iOS
慕神8447489 2023-05-02 17:13:31
怎么实现一个精准的Timer?我写了如下的代码进行测试。1. 在主线程中。NSTimer *tiemer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(output) userInfo:nil repeats:YES]; - (void) output{    NSLog(@"-------------"); }发现间隔时间大概在正负5毫秒之间徘徊。就像这样:2013-05-02 16:25:32.550 TestDemoArc[21139:907] -------------2013-05-02 16:25:33.549 TestDemoArc[21139:907] -------------2013-05-02 16:25:34.554 TestDemoArc[21139:907] -------------2013-05-02 16:25:35.555 TestDemoArc[21139:907] -------------如果在主线程中做一些操作,比如:    int j = 0;     for (int i = 0; i<100000000; i++) {         j = j+i;    }时间间隔会变为两秒。就像这样:2013-05-02 16:38:32.437 TestDemoArc[21207:907] -------------2013-05-02 16:38:34.437 TestDemoArc[21207:907] -------------2013-05-02 16:38:36.437 TestDemoArc[21207:907] -------------2013-05-02 16:38:38.439 TestDemoArc[21207:907] -------------2013-05-02 16:38:40.437 TestDemoArc[21207:907] -------------当然,用block放到子线程里就只有1毫秒左右的偏差了。现在想问怎么做一个Timer,保证有在1毫秒以下的偏差。
查看完整描述

2 回答

?
绝地无双

TA贡献1946条经验 获得超4个赞

IOS中可以使用"mach_absolute_time"获取到CPU的tickcount的计数值,可以通过"mach_timebase_info"函数获取到纳秒级的精确度 代码如下: uint64t start = 0; uint64t end = 0; uint64_t elapsed = 0;

mach_timebase_info_t timeBaseInfo = mach_timebase_info(info);start = mach_absolute_time();// dosomething
// .....end = mach_absolute_time();elapsed = end - start;// convert to nanoseconds
uint64_t elapsedNanoSeconds = elapsed * sTimebaseInfo.numer / sTimebaseInfo.denom;

但是CPU线程之间的调度肯定要花费时间,所以只能尽可能的精确。


查看完整回答
反对 回复 2023-05-04
?
郎朗坤

TA贡献1921条经验 获得超9个赞

计时器不准确的原因是,计时器只有在 runLoop 的一次循环中被检查,所以如果在上次循环中做了什么耗时的操作,那么计时器就被延后执行了。

正确的方法应该是新开一个线程,然后在新开的线程里设定一个 timer,并执行。

__block TestViewController *blockSelf = self;dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    blockSelf->_timer=[NSTimer scheduledTimerWithTimeInterval:1.0
                                            target:blockSelf
                                        selector:@selector(caculateLeftTimeForTomorrow)
                                          userInfo:nil
                                           repeats:YES] ;
    [[NSRunLoop currentRunLoop] addTimer:blockSelf->_timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
});


查看完整回答
反对 回复 2023-05-04
  • 2 回答
  • 0 关注
  • 235 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信