NSTimer CADisplayLink GCD

昨天遇到一个问题,把NSTimer设置为0.001秒无效,而且设置为0.001秒最终也不是0.1秒执行一次,隐约记得NSTimer的精度是0.1秒,翻了翻笔记,果然精度是1毫秒,小小的复习了下,下面发表一些个人看法吧。。。非教材,纯属个人看法,说的不好,请指出。。

NSTimer

个人看法

  • NSTimer是存在延迟的,因为NSTimer是需要加入RunLoop,在RunLoop中执行任务,如果RunLoop正在执行一个连续性的任务,在执行一个任务的时候会计算这执行下一个任务的延迟,一个正在执行的timer,在停止的时候会把本周起的任务执行完,再开启下一个已经计算好的延迟周期的任务,所以停止不一定停止,需要把计算好的任务执行完毕才能停止,个人看法。。。

用法

创建方法

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(action:) userInfo:nil repeats:NO];

属性

TimerInterval : 执行之前等待的时间。比如设置成1.0,就代表1秒后执行方法
target : 需要执行方法的对象。
selector : 需要执行的方法
repeats : 是否需要循环

使用上面的方式创建,timer会自动加入MainRunloop的NSDefaultRunLoopMode中。下面的方式创建定时器,就需要手动加入Runloop了
NSTimer *timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

timer停止

[timer invalidate];

CADisplayLink

一些个人看法

  • CADisplayLink刷新频率非常强大,可以和屏幕的刷新频率同步,这个屌!CADisplayLink会以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。通常情况下,iOS设备屏幕的刷新率为60次/秒。
  • 还是有延迟,iOS设备的屏幕刷新频率一般情况下是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当的高。但如果调用的方法比较耗时,超过了屏幕刷新周期,就会导致跳过若干次回调调用机会。

使用

创建方法

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

停止方法

[displayLink invalidate];

displayLink = nil;

属性

frameInterval
NSInteger类型的值,用来设置间隔多少帧调用一次selector方法,默认值是1,即每帧都调用一次。

duration
readOnly的CFTimeInterval值,表示两次屏幕刷新之间的时间间隔。需要注意的是,该属性在target的selector被首次调用以后才会被赋值。selector的调用间隔时间计算方式是:调用间隔时间 = duration × frameInterval。

GCD

一次性执行

double delayInSeconds = 2.0;

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);

dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

重复执行

NSTimeInterval period = 1.0; //设置时间间隔

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //每秒执行

dispatch_source_set_event_handler(_timer, ^{

//在这里执行事件

});

dispatch_resume(_timer);
坚持原创技术分享,您的支持将鼓励我继续创作!