内存管理-CADisplayLink, NSTimer
CADisplayLink
定义
- 一个定时器对象,它可以让你与屏幕刷新频率相同的速率来刷新你的视图。就说CADisplayLink是用于同步屏幕刷新频率的计时器。
- 在应用中创建一个新的CADisplayLink对象,把它添加到一个runloop中,并给它提供一个target和selector在屏幕刷新的时候调用。
API
1 | //初始化 |
NSTimer
定义
- OC中的计时器(时钟),可每隔一段时间执行一次。
API
1 | //初始化 |
区别
原理不同
CADisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。CADisplayLink以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。NSTimer以指定的模式注册到runloop后,每当设定的周期时间到达后,runloop会向指定的target发送一次指定的selector消息。
周期设置不同
- iOS设备的屏幕刷新频率(FPS)是60Hz,因此
CADisplayLink的selector默认调用周期是每秒60次,这个周期可以通过frameInterval属性设置,CADisplayLink的selector每秒调用次数=60/frameInterval。比如当frameInterval设为2,每秒调用就变成30次。因此,CADisplayLink周期的设置方式略显不便。 NSTimer的selector调用周期可以在初始化时直接设定,相对就灵活的多。
精度不同
- iOS设备的屏幕刷新频率是固定的,
CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。 NSTimer的精确度就显得低了点,比如NSTimer的触发时间到的时候,runloop如果在阻塞状态,触发时间就会推迟到下一个runloop周期。并且NSTimer新增了tolerance属性,让用户可以设置可以容忍的触发的时间的延迟范围。
使用场景
CADisplayLink使用场合相对专一,适合做UI的不停重绘,比如自定义动画引擎或者视频播放的渲染。NSTimer的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。
用法
1 | @interface ViewController () |
循环引用
原因
- self对
CADisplayLink强引用,CADisplayLink对target强引用,target对self强引用,造成循环引用NSTimer也有类似问题,NSTimer的scheduledTimerWithTimeInterval创建方式会造成循环引用
解决方案
- _ _weak, 使用block 弱引用均无法解决
- 使用代理对象
代理对象,继承NSObject
1 | @interface HXProxy1 : NSObject |
代理对象,继承NSProxy
1 | @interface HXProxy : NSProxy |
GCD定时器执行任务封装
- NSTimer依赖于RunLoop,如果RunLoop的任务过于繁重,可能会导致NSTimer不准时
- GCD的定时器会更加准时
1 | //.h |
使用方法
1 | NSString *task = [HXTimer execTask:self |
参考
李明杰老师课件- objc源码
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ivan's Blog!
评论






