美文网首页
2018-02-01

2018-02-01

作者: 思绪飘零ing | 来源:发表于2018-02-01 12:00 被阅读0次

    iOS【NSTimer到底准不准?】

    2018.2.1  最近面试 被 问道 NSTimer 到底准不准的问题 当时有点蒙 因为没爬过这个坑 所以没法打出来 特此记录一下

    当时 就知道 人家 问了  那么就说明 NSTimer 一定是不准的 但是  问题点就是 在这个 准不准的标准是什么呢 ?  

    定时器 很简单  回来后做了个测试  自己写了个 定时器 

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

        if (!_timer) {

            _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(logInfo) userInfo:nil repeats:YES];

        }

    }

    - (void)logInfo {

        NSLog(@"timer test");

    }

     结果是 

    2018-02-01 09:12:32.566622+0800 QTimer[20276:7878806] timer test

    2018-02-01 09:12:33.566811+0800 QTimer[20276:7878806] timer test

    2018-02-01 09:12:34.566510+0800 QTimer[20276:7878806] timer test

    2018-02-01 09:12:35.567532+0800 QTimer[20276:7878806] timer test

    2018-02-01 09:12:36.567613+0800 QTimer[20276:7878806] timer test

    2018-02-01 09:12:37.566615+0800 QTimer[20276:7878806] timer test

    2018-02-01 09:12:38.567415+0800 QTimer[20276:7878806] timer test

    2018-02-01 09:12:39.567650+0800 QTimer[20276:7878806] timer test

    2018-02-01 09:12:40.566592+0800 QTimer[20276:7878806] timer test

    可以看出来  定时器 并不是准确的  1S的  误差 在 1毫秒以内  应该是很准的了

    但是 确实 是不准的    我们继续 给 定时器 的方法里面 继续 添加更多的耗时代码;

    - (void)logInfo {

        int count = 0;

        for (int i = 0; i < 1000000000; i++) {

            count += i;

        }

        NSLog(@"timer test");

    }

    结果

    2018-02-01 09:40:38.194879+0800 QTimer[9749:3330951] timer test

    2018-02-01 09:40:44.188463+0800 QTimer[9749:3330951] timer test

    2018-02-01 09:40:50.172012+0800 QTimer[9749:3330951] timer test

    2018-02-01 09:40:56.172139+0800 QTimer[9749:3330951] timer test

    2018-02-01 09:41:02.179022+0800 QTimer[9749:3330951] timer test

    2018-02-01 09:41:08.170254+0800 QTimer[9749:3330951] timer test

    2018-02-01 09:41:14.169011+0800 QTimer[9749:3330951] timer test

    可以清晰的看出来 时间已经不准的 准确的来说  那么原因是什么呢 经过 查找资料得知

    定时器被添加在主线程中,由于定时器在一个RunLoop中被检测一次,所以如果在这一次的RunLoop中做了耗时的操作,当前RunLoop持续的时间超过了定时器的间隔时间,那么下一次定时就被延后了。

    意思就是说  你这个 定时器的方法里面 相当于 一个runloop  只有当 方法 里面代码 走完了 定时器 才会 继续 起作用 就是说  当  定时器 方法 里面 的耗时操作 超过了 定时器的时间间隔  那么 就会 导致 定时方法里面的代码 执行之后  才会继续定时器 再间隔一s 之后执行这个方法 (这个情况 会出现的 前提是 定时器里面的方法 的耗时操作 超过了 定时的 时间间隔);

    接下来就是 解决方法了  既然 执行方法 会 阻碍NSTtimer  那么我们就把他们分开  

    解决方法:

    1、在子线程中创建timer,在主线程进行定时任务的操作

    2、在子线程中创建timer,在子线程中进行定时任务的操作,需要UI操作时切换回主线程进行操作

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread)object:nil];2[thread start];

    - (void)newThread2{

     @autoreleasepool

     {

    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(addTime) userInfo:nil repeats:YES];

     [[NSRunLoop currentRunLoop] run];

     }

    }

    在子线程中将NSTimer以默认方式加到该线程的runloop中,启动子线程。(注意 timer 的runloop 模式的形象 因为是在子线程里面 所以 runloop的model 没考虑 如果特殊情况 考虑runloop的model  就不采用 默认的方式创建timer 手动添加 到runloop 里面 去 采用commodmodel )

    或者干脆 直接用多线程GCD 定时器  也是 多线程方式  回归主线程 刷新UI 

    相关文章

      网友评论

          本文标题:2018-02-01

          本文链接:https://www.haomeiwen.com/subject/smfdzxtx.html