屏幕刷新与UI更新不同步;屏幕刷新由硬件(+GPU)保证,UI更新由软件(CPU保证)。

出现卡顿的原因是软件的计算速度跟不上硬件的刷新速度。

一 简介

1 所在框架

CADisplayLink和其它CoreAnimation类一样,都是在QuartzCore.framework里。

2 功能

CADisplayLink最主要的特征是能提供一个周期性的调用我们赋给它的selector的机制,从这点上看它很像定时器NSTimer。

3 使用方式

- (void)startDisplayLink
{
self.displayLink = [CADisplayLink displayLinkWithTarget:self
selector:@selector(handleDisplayLink:)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
} - (void)handleDisplayLink:(CADisplayLink *)displayLink
{
//do something
} - (void)stopDisplayLink
{
[self.displayLink invalidate];
self.displayLink = nil;
}

当把CADisplayLink对象add到runloop中后,selector就能被周期性调用,类似于NSTimer被启动了;执行invalidate操作时, CADisplayLink对象就会从runloop中移除,selector 调用也随即停止,类似于NSTimer的invalidate方法。

特性

下面结合NSTimer来介绍 CADisplayLink,与NSTimer不同的地方有:

1 原理不同

CADisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。 CADisplayLink以特定模式注册到runloop后, 每当屏幕显示内容刷新结束的时候,runloop就会向 CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。

NSTimer以指定的模式注册到runloop后,每当设定的周期时间到达后,runloop会向指定的target发送一次指定的selector消息。

2 周期设置方式不同

iOS设备的屏幕刷新频率(FPS)是60Hz,因此CADisplayLink的selector 默认调用周期是每秒60次,这个周期可以通过frameInterval属性设置, CADisplayLink的selector每秒调用次数=60/ frameInterval。比如当 frameInterval设为2,每秒调用就变成30次。因此, CADisplayLink 周期的设置方式略显不便。

NSTimer的selector调用周期可以在初始化时直接设定,相对就灵活的多。

3 精确度不同

iOS设备的屏幕刷新频率是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。

NSTimer的精确度就显得低了点,比如NSTimer的触发时间到的时候,runloop如果在忙于别的调用,触发时间就会推迟到下一个runloop周期。更有甚者,在OS X v10.9以后为了尽量避免在NSTimer触发时间到了而去中断当前处理的任务,NSTimer新增了tolerance属性,让用户可以设置可以容忍的触发的时间范围。

4 使用场合

从原理上不难看出, CADisplayLink 使用场合相对专一, 适合做界面的不停重绘,比如视频播放的时候需要不停地获取下一帧用于界面渲染。

NSTimer的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。

三 重要属性

下面不完整的列出了 CADisplayLink的几个重要属性:

1、 frameInterval

可读可写的NSInteger型值,标识间隔多少帧调用一次selector方法,默认值是1,即每帧都调用一次。官方文档中强调,当该值被设定小于1时,结果是不可预知的。

2、duration

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

现存的iOS设备屏幕的FPS都是60Hz,这一点可以从CADisplayLink的duration属性看出来。duration的值都是0.166666…,即1/60。尽管如此,我们并没法确定苹果不会改变 FPS ,如果以后某一天将 FPS 提升到了120Hz了怎么办呢?这时,你设置了frameInterval属性值为2期望每秒刷新30次,却发现每秒刷新了60次,结果可想而知,出于安全考虑,还是先根据duration判断屏幕的 FPS再去使用 CADisplayLink 。

3、timestamp

只读的CFTimeInterval值,表示屏幕显示的上一帧的时间戳,这个属性通常被target用来计算下一帧中应该显示的内容。

虽然名为时间戳,但这和常见的unix时间戳差异很大,事实上这是CoreAnimation使用的时间格式。每个CALayer都有一个本地时间(CALayer本地时间的具体作用会在后续文章中说明),可以获取当前CALayer的本地时间并打印:

CFTimeInterval localLayerTime = [myLayer convertTime:CACurrentMediaTime() fromLayer:nil];
NSLog("localLayerTime:%f",localLayerTime);

四、注意

iOS并不能保证能以每秒60次的频率调用回调方法,这取决于:

1、CPU的空闲程度

如果CPU忙于其它计算,就没法保证以60HZ执行屏幕的绘制动作,导致跳过若干次调用回调方法的机会,跳过次数取决CPU的忙碌程度。

2、执行回调方法所用的时间

如果执行回调时间大于重绘每帧的间隔时间,就会导致跳过若干次回调调用机会,这取决于执行时间长短。

五、参考文档

1、官方文档

https://developer.apple.com/library/ios/documentation/QuartzCore/Reference/CADisplayLink_ClassRef/Reference/Reference.html#//apple_ref/doc/uid/TP40009031-CH1-DontLinkElementID_1

2、官方使用CADisplayLink播放视频的例子

https://developer.apple.com/library/ios/samplecode/AVBasicVideoOutput/Introduction/Intro.html#//apple_ref/doc/uid/DTS40013109

作者:小杂鱼
链接:https://www.jianshu.com/p/72fedadf92e3
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

CADisplayLink & NSTimer的更多相关文章

  1. Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用

    OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ...

  2. iOS笔记052- Quartz2D-绘图

      简介 Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作       绘制图形 : 线条\三角形\矩形\圆\弧等       绘制文字       绘 ...

  3. IOS NSTimer和CADisplayLink的用法

    IOS--NSTimer和CADisplayLink的用法 NSTimer初始化器接受调用方法逻辑之间的间隔作为它的其中一个参数,预设一秒执行30次.CADisplayLink默认每秒运行60次,通过 ...

  4. CADisplayLink以及和NSTimer的区别

    什么是CADisplayLink CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器.我们在应用中创建一个新的 CADisplayLink 对象,把它添加到一个r ...

  5. 定时器 NSTimer 和 CADisplayLink

    NSTimer *timer; CADisplayLink *caDisplayLink; int timeCount; - (void)viewDidLoad { [super viewDidLoa ...

  6. [转]NSTimer和CADisplayLink的基本用法

    简要区别:NSTimer初始化器接受调用方法逻辑之间的间隔作为它的其中一个参数,预设一秒执行30次.CADisplayLink默认每秒运行60次,通过它的frameInterval属性改变每秒运行帧数 ...

  7. iOS开发中深入理解CADisplayLink和NSTimer

    一.什么是CADisplayLink 简单地说,它就是一个定时器,每隔几毫秒刷新一次屏幕. CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器.我们在应用中创建一 ...

  8. iOS - CADisplayLink与NSTimer

    一.CADisplayLink简介 CADisplayLink 是一个定时器对象可以让你的应用以与显示器的刷新界面相同的频率进行绘图. 应用如果想要创建 display link ,需要提供一个目标对 ...

  9. iOS开发--计时器-NSTimer与CADisplayLink

    如果程序要让某个方法重复执行,可以借助定时器来完成.CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器,NSTimer的精确度低了点,比如NSTimer的触发时间 ...

随机推荐

  1. 构造定律(constructal law)-构造定律作为第二个时间箭头,将和热力学第二定律一道将宇宙推向无序。

    优化系统结构,使信息和物质流在结构内的流动更畅通. 构造定律(constructal law) 由Adrian Bejan于1995创立的构造定律(constructal law):   For a ...

  2. WIN系统查询版本

    cmd -> DISM /online /Get-CurrentEdition //查询系统版本 WIN+R -> slmgr.vbs -ipk 查询系统注册信息slmgr.vbs -dl ...

  3. JS防抖与节流

    在进行窗口的resize.scroll,输入框内容校验等操作时,如果事件处理函数调用的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕.此时我们可以采用debounce(防抖)和throttle( ...

  4. iview关于menu结合router问题

    #iview关于menu结合router问题 1. Menu.Item下router问题: 直接在Menu标签上绑定on-select事件,可以获取到name(name为元素绑定name) <M ...

  5. 【ACM-ICPC 2018 南京赛区网络预赛 E】AC Challenge

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 写个DP 设f[j]表示已经做的题的状态为j的情况下接着选能获得的最大分数. 显然是个倒推. 记忆化搜索一波 dfs(i,j) 表示 ...

  6. 警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclips

    警告: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclips ...

  7. File System Design Case Studies

    SRC=http://www.cs.rutgers.edu/~pxk/416/notes/13-fs-studies.html Paul Krzyzanowski April 24, 2014 Int ...

  8. redis-ubuntu环境下安装

    ubuntu环境下联网安装 进去系统后,首先修改root的密码 命令 sudo passwd 设置新的密码:XXX 切换为root操作 $ wget http://download.redis.io/ ...

  9. ISAM Indexed Sequential Access Method 索引顺序存取方法

    ISAM Indexed Sequential Access Method 索引顺序存取方法 学习了:https://baike.baidu.com/item/ISAM/3013855 是IBM发展起 ...

  10. Unity3D 人形血条制作小知识

    这几天用Unity3D做个射击小游戏,想做个人形的血条.百思不得其解,后来问了网上的牛牛们,攻克了,事实上挺简单的,GUI里面有个函数DrawTextureWithTexCoords就能够实现图片的裁 ...