Contents
  1. 1. NSTimer与GCD
    1. 1.1. 一: 常用延时调用的方式
    2. 1.2. 二: 非GCDTimer使用注意
    3. 1.3. 三: GCDTimer
    4. 1.4. 四: 时间准确性
      1. 1.4.1. NSTimer-较低
      2. 1.4.2. GCDTimer-准确
      3. 1.4.3. CADisplayLink-较准确
    5. 1.5. 参考

NSTimer与GCD

一: 常用延时调用的方式

  • NSObject的performSelector…
    • 实际是在当前线程创建了一个Timer去执行任务
  • NSTimer
    • +timerWithTimeInterval
    • +scheduledTimerWithTimeInterval
  • GCDTimer
    • dispatch_after

二: 非GCDTimer使用注意

  • 必须有一个活跃的RunLoop

performSelectorscheduledTimerWithTimeInterval 都是基于RunLoop的.
主线程没关系,因为不会停止
如果在子线程的话需要手动开启RunLoop否则调用将会是无效的

  • NSTimer的创建于撤销必须在同一个线程操作
  • performSelector创建取消也必须在同一个线程操作
  • 内存泄露问题
    • Timer的target会被Timer强引用
    • Timer被RunLoop强引用
    • 所以想在dealloc里去invalidate Timer是不可能的
    • 计时完成后手动去invalidate
      • RunLoop解除对Timer的引用
      • Timer解除对Target的引用

三: GCDTimer

  • 系统会自动处理线程逻辑
  • 无须关心RunLoop问题
    • block的循环引用还是要注意下
      • 缺点
      • 没有repeats选项
      • 直接使用代码比较多,最好封装一下

四: 时间准确性

NSTimer-较低

CFRunloopTimerRef 底层基于 mk_timer 实现
基于RunLoop运行
使用之前必须注册到RunLoop,但RunLoop为节省资源并不会在非常准确的时机调用定时器,执行任务时,可能错过一个时间点只能等下个时间点再执行
NSTimer有个tolerance属性可以用于设置宽容度,可提高精准度

GCDTimer-准确

CADisplayLink是一个执行频率(fps)和屏幕刷新相同(可以修改preferredFramesPerSecond改变刷新频率)的定时器,它也需要加入到RunLoop才能执行。与NSTimer类似,CADisplayLink同样是基于CFRunloopTimerRef实现,底层使用mk_timer(可以比较加入到RunLoop前后RunLoop中timer的变化)。和NSTimer相比它精度更高(尽管NSTimer也可以修改精度),不过和NStimer类似的是如果遇到大任务它仍然存在丢帧现象。通常情况下CADisaplayLink用于构建帧动画,看起来相对更加流畅,而NSTimer则有更广泛的用处。

参考

https://www.jianshu.com/p/0c050af6c5ee
https://www.cnblogs.com/kenshincui/p/6823841.html

Contents
  1. 1. NSTimer与GCD
    1. 1.1. 一: 常用延时调用的方式
    2. 1.2. 二: 非GCDTimer使用注意
    3. 1.3. 三: GCDTimer
    4. 1.4. 四: 时间准确性
      1. 1.4.1. NSTimer-较低
      2. 1.4.2. GCDTimer-准确
      3. 1.4.3. CADisplayLink-较准确
    5. 1.5. 参考