屏幕刷新与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. Javaee 方法的构建和调用

    主类: package Szy02; public class Person { String name; int age; String sex; public Person(){ } public ...

  2. luogu 3467 [POI2008]PLA-Postering 单调栈

    题目描述: Description N个矩形,排成一排. 现在希望用尽量少的矩形海报Cover住它们. Input 第一行给出数字N,代表有N个矩形.N在[1,250000] 下面N行,每行给出矩形的 ...

  3. C++基础 (1) 第一天 C++相对C的改进 命名空间 引用

    第一天 语法 STL 数据结构  设计模式… 2 C++语言的间接 C++ = C语言+面向对象 本贾尼 语言分类: 不关心效率 只关心架构:java/脚本语言 效率:(内存要自己管理了,操作指针)C ...

  4. BZOJ 3439 Kpm的MC密码 (Trie树+线段树合并)

    题面 先把每个串反着插进$Trie$树 每个节点的子树内,可能有一些节点是某些字符串的开头 每个节点挂一棵权值线段树,记录这些节点对应的原来字符串的编号 查询的时候在线段树上二分即可 为了节省空间,使 ...

  5. [CodeForces]981C Useful Decomposition

    李煜东dalao今天给我们讲课了QwQ ppt上一道题 英文题说一下题意吧,以后又看不懂了 将一棵树分割成多个简单路径,每个边只能在一条路径上,但至少有一个公共节点. 输出简单路径分割方法/No 由题 ...

  6. Linux 程序包管理-YUM

    前端工具YUM管理程序包:  rpm管理软件虽然方便,但是需要手工解决软件包的依赖关系:很多时候安装一个软件需要首先安装一个或多个(有时多达上百个)其它软件,手工解决很复杂:使用yum可以解决这个问题 ...

  7. 运用cat EOF添加文件

    [root@fyc14 nginx1]# cat <<EOF > /etc/yum.repos.d/nginx.repo> [nginx]> name=nginx rep ...

  8. 你必须搞清楚的String,StringBuilder,StringBuffer

    String,StringBuilder 以及 StringBuffer 这三个类的关系与区别一直是 Java 的经典问题,这次就来讲一下关于这三个类的一些知识 一. 简单对比 String : 字符 ...

  9. 【转】sql 基本语法

    简单语法:http://www.cnblogs.com/lyhabc/p/3691555.html 数据类型宽度:http://www.cnblogs.com/lyhabc/p/3696629.htm ...

  10. 【翻译自mos文章】 在错误的从os级别remove掉 trace file 之后,怎么找到该trace file的内容?

    在错误的从os级别remove掉 trace file 之后,怎么找到该trace file的内容? 參考原文: How to Find the Content of Trace File Gener ...