GCD定时器替换NSTimer不准的问题

1.NSTimer会受到RunLoop中Modes的影响;
2.GCD创建的定时器不受RunLoop中Modes影响;

// 如果在子线程中创建Timer,那么当我们add到RunLoop的时候有NSDefaultRunLoopMode和
    // NSRunLoopCommonModes两种模式可以选择
    // 这里不像主线程,子线程需要创建loop并且run起来,不然是不会连续跑任务的
    // 不准的原因在于,当我们在NSDefaultRunLoopMode模式下跑的时候,我们滚动例如TableView的时候切换到
    // TrackingMode,loop会退出当前mode,重新进入指定的mode,如果NSTimer不是加到NSRunLoopCommonModes
    // 那么任务跑起来一直在切换,肯定会不准
    NSTimer *timer=  [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];

GCD创建定时器

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    // @property (nonatomic,strong) dispatch_source_t timer;
    /**
      创建一个定时器(dispatch_source_t本质还是个OC对象)
      
     参数1:代表创建一个定时器
     参数4:队列
     这里的强引用是因为,当我定时器延时几秒调用的时候,局部变量就死了,我们需要强引用起来
     */
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    /**
     设置定时器
     参数1:定时器对象
     参数2:GCD dispatch_time_t 里面的都是纳秒 创建一个距离现在多少秒开启的任务
     参数3:间隔多少秒调用一次
     */
    dispatch_source_set_timer(self.timer, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), (uint64_t)(1.0 * NSEC_PER_SEC), 0);
    // 设置回调
    dispatch_source_set_event_handler(self.timer, ^{
        NSLog(@"定时器%@",[NSThread currentThread]);
    });

    // 启动
    dispatch_resume(self.timer);
}

RunLoop详解传送门

你可能感兴趣的:(基础知识)