美文网首页
iOS 中关于定时器的一些理解

iOS 中关于定时器的一些理解

作者: Nulll | 来源:发表于2019-03-14 11:25 被阅读0次

一、NSTimer 关于定时器的时间误差问题。

1)创建一个循环定时器并且执行循环操作。

self.timer = [NSTimer scheduledTimerWithTimeInterval:1.00 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];

- (void)timerRun {
    NSLog(@"timerTest");
}

打印结果如下:


屏幕快照 2019-03-14 上午11.11.30.png

这里的打印可以看出时间上有一定的误差,虽然这个误差已经很小了。但误差确实存在。。
如果在循环里面加上计算任务,

- (void)timerRun { 
    NSLog(@"timerTest");
    int count = 0;
    for (long i = 0; i < 1000000000; i++) {
        count += 1;
    }

再来看看打印的结果,


屏幕快照 2019-03-14 上午11.15.32.png

现在误差就很明显了。

2)原因分析:

定时器被添加在主线程中,由于定时器在一个RunLoop中被检测一次,所以如果在这一次的RunLoop中做了耗时的操作,当前RunLoop持续的时间超过了定时器的间隔时间,那么下一次定时就被延后了。
RunLoop 有三个模式,NSDefaultRunLoopMode; 默认模式
UITrackingRunLoopMode; UI滚动模式
NSRunLoopCommonModes; 上面两种模式的共同模式

NSTimer默认是添加在RunLoop的 NSDefaultRunLoopMode 模式中。
所以要将 NSTimer 添加在 NSRunLoopCommonModes 模式中;

二、GCD timer

    //获得队列
    dispatch_queue_t dispatchQueue = dispatch_get_global_queue(0, 0);
    //创建一个gcd定时器 (dispatch_source_t timer:dispatch_source_t本质还是个OC对象,是个局部变量,需要强引用,不然下面使用无效)
    self.gcdTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatchQueue);
    //OC对象%@可以打印
    NSLog(@"%@", self.gcdTimer);
    //设置定时器的各种属性(几时开始,每隔多长时间执行一次)
    //GCD时间参数,一般是纳秒 NSEC_PER_SEC 纳秒单位等于一秒;DISPATCH_TIME_NOW当前时间
    dispatch_time_t start = DISPATCH_TIME_NOW;
    uint64_t interval = (uint64_t)(2.0 *NSEC_PER_SEC);
    dispatch_source_set_timer(self.gcdTimer, start, interval, 0);
    dispatch_source_set_event_handler(self.gcdTimer, ^{

        [self timerRun];
    });
    //启动定时器
    dispatch_resume(self.gcdTimer);

- (void)timerRun {
    
    NSLog(@"timerTest");
    int count = 0;
    for (long i = 0; i < 1000000000; i++) {
        count += 1;
    }
}

GCD Timer 同样也会有一样的误差。


屏幕快照 2019-03-14 下午4.49.19.png

三、解决办法

1)将NStimer 添加在子线程中执行。然后在需要UI操作的地方放置在主线程里面。

dispatch_queue_t queue = dispatch_queue_create("const_char_dispatch_timer", DISPATCH_QUEUE_CONCURRENT);
    __weak typeof(self)ws = self;
    dispatch_async(queue, ^{
            __strong typeof(ws)ss = ws;
            ss.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
            [[NSRunLoop currentRunLoop] addTimer:ss.timer forMode:NSRunLoopCommonModes];
            [[NSRunLoop currentRunLoop] run];

    });
- (void)timerRun {
    
    NSLog(@"timerTest");
    dispatch_queue_t queue = dispatch_queue_create("const_char_dispatch_timer", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(queue, ^{

        int count = 0;
        for (long i = 0; i < 1000000000; i++) {
            count += 1;
        }
    });

}

相关文章

  • iOS 中关于定时器的一些理解

    一、NSTimer 关于定时器的时间误差问题。 1)创建一个循环定时器并且执行循环操作。 打印结果如下: 这里的打...

  • iOS进阶-谈谈定时器

    目录 iOS提供定时器API 定时器开发中的坑 一、 iOS提供定时器API 二、定时器开发中的坑 2.1、必须办...

  • iOS中的定时器

    点击这里>> cocoaChina: iOS中的定时器 iOS中定时器有三种,分别是NSTimer、CADispl...

  • GCD定时器使用

    iOS中的常用定时器分为这几类: NSTimer CADisplayLink GCD定时器 选择GCD定时器原因:...

  • iOS:NSTimer的几种创建方式

    在iOS开发中,经常会用到定时器,iOS中常用的定时器有三种:NSTimer,GCD,CADisplayLink。...

  • 定时器的使用介绍

    iOS中的定时器大致分为这几类: NSTimer CADisplayLink GCD定时器 (一)NSTimer ...

  • NSTimer

    深入NSTimer(iOS)iOS 中的 NSTimer关于NSRunLoop和NSTimer的深入理解

  • iOS 中关于列表滚动流畅方案的一些探讨

    iOS 中关于列表滚动流畅方案的一些探讨 iOS 中关于列表滚动流畅方案的一些探讨

  • iOS Timer

    iOS开发中定时器经常会用到,iOS中常用的定时器有三种,分别是NSTime,CADisplayLink和GCD。...

  • iOS三大定时器

    iOS开发中定时器经常会用到,iOS中常用的定时器有三种,分别是NSTime,CADisplayLink和GCD。...

网友评论

      本文标题:iOS 中关于定时器的一些理解

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