Core Animation系列之CADisplayLink

原创 2014年03月29日 17:52:19
Core Animation系列之CADisplayLink
作者:wangzz
原文地址:http://blog.csdn.net/wzzvictory/article/details/22417181
转载请注明出处
如果觉得文章对你有所帮助,请通过留言或关注微博、微信公众帐号wangzzstrive来支持我,谢谢!

一直以来都想好好学习下CoreAnimation,奈何涉及的东西太多,想要一次性全部搞定时间上不允许,以后会断断续续的补全。最近项目里用到了CADisplayLink,就顺便花点时间看了看。

一、简介

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用来计算下一帧中应该显示的内容。
打印timestamp值,其样式类似于:
179699.631584
虽然名为时间戳,但这和常见的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


相关文章推荐

iOS --- 使用CADisplayLink来实现定时任务

CADisplayLink是以屏幕刷新频率将内容绘制到屏幕上的定时器。使用的时候,先创建一个CADisplayLink对象,将其添加到一个RunLoop中,并设置target和selector方法,则...

CADisplayLink简单应用

在iOS 中想到定时循环就会想到NSTime和CADisplayLink NSTime可以设置指定的时间以及是否需要循环。 CADisplayLink则是默认循环直至其失效。其循环间隔为每秒60次...
  • qqMCY
  • qqMCY
  • 2016年03月04日 10:07
  • 585

CADisplayLink以及定时器的使用

第一种: 用CADisplayLink可以实现不停重绘。- (CADisplayLink *)link { if (!_link) { // 创建定时器,一秒钟调用rotat...

CADisplayLink

CADisplayLink 是一个用于显示的定时器,  它可以让用户程序的显示于屏幕的硬件刷新保持同步。   一   创建CADisplayLink对象         可以用 CADisplay...
  • volvet
  • volvet
  • 2016年03月03日 22:43
  • 381

计算当前CADisplayLink时间

_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayAction:)]; [_...

深入理解CADisplayLink和NSTimer

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

H264编码器参数理解 (部分)“I帧”和“帧间距”等的理解

写作背景:最近在研究H264编码器的参数,里面的参数不太懂,其中包括: 1)  30 # i intervals  // I 帧间距 2)30 # idr intervals// idr帧间距 ...

V4L2命令之 VIDIOC_ENUM_FMT VIDIOC_ENUM_FRAMESIZES VIDIOC_ENUM_FRAMEINTERVALS

http://linuxtv.org/downloads/v4l-dvb-apis/vidioc-enum-frameintervals.html VIDIOC_ENUM_FMT Name...

视图渲染、CPU和GPU卡顿原因及其优化方案

视图渲染过程: 1、CPU 计算好显示内容提交到 GPU 2、GPU 渲染完成后将渲染结果放入帧缓冲区 3、视频控制器会按照 VSync 信号逐行读取帧缓冲区的数据,经过可能的数模转换传递给显示器显示...

CADisplayLink 及定时器的使用

第一种: 用CADisplayLink可以实现不停重绘。 例子: CADisplayLink* gameTimer; gameTimer = [CADis...
  • ch_soft
  • ch_soft
  • 2013年07月22日 14:38
  • 34533
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Core Animation系列之CADisplayLink
举报原因:
原因补充:

(最多只允许输入30个字)