CADisplaylink 及其应用

什么是 CADisplaylink?

对于什么是 CADisplaylink. 我们先来看看苹果官方文档中的描述:

A CADisplayLink object is a timer object that allows your application to synchronize its drawing to the refresh rate of the display.

从中可以看出, CADisplaylink 是一个计时器对象,可以使用这个对象来保持应用中的绘制与显示刷新的同步。更通俗的讲,电子显示屏都是由一个个像素点构成,要让屏幕显示的内容变化,需要以一定的频率刷新这些像素点的颜色值,系统会在每次刷新时触发 CADisplaylink。

CADisplaylink 的使用方法

使用 CADisplaylink 时需要先用一个 target 和 一个 selector 来创建一个 display link 对象,然后把创建的对象加到 runloop 中,代码如下:

CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTriggered)];
[displayLink setPaused:YES];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

CADisplayLink 对象一旦加入 Runloop 中,则会在屏幕需要刷新时回调 selector。如果要暂停对 selector 的调用,可以把 paused 属性设置为 YES 来实现。当不再使用 CADisplayLink 时,需要调用 invalidate 方法从所有的 Runloop 中将其移除。

在 selector 中可以通过 CADisplayLink 对象的属性 duration、frameInterval 和 timestamp 获取帧率和时间信息。关于他们的使用将在下面的实例中阐述。

应用之自定义动画

UIKit 和 Core Animation framework 中已经为开发者实现各式动画提供了丰富的接口。这些接口不仅可以实现简单的平移、旋转、切变、拉伸或者他们的组合,还可以控制这些动画发生的时间函数(Timing Functions)。

当动画中元素在空间上的位置变化或者在时间上的速度变化不能使用苹果提供的简单基本变换来叠加模拟时,此时我们就需要使用更复杂的接口来实现,如使用关键帧动画接口或者自定义时间函数。对于某些特别的动画,则可以借助 Display Link 来实现,比如下面的动画:

初看这个动画并不复杂,但是设计师重点强调了图标下落时要有重力的感觉,所以图标下落和弹起的速度是有变化的,图标本身在竖直方向上也有因为重力和碰撞产生的压缩和舒张,这些模拟真实物理特性的效果要使用苹果提供的基本变换和时间函数来实现将会花费很多时间去调试各种参数才能达到设计师一模一样的效果。鉴于设计师已经提供了 avi 格式的动画视频,并且动画中元素位置的变化也比较简单,于是笔者决定利用 Matlab 提取动画视频里各帧中物体的位置信息,然后在 selector 中根据这些位置信息更新 view 或 layer 的约束或者 frame 即可。

此方案无需考虑动画中元素的运动细节,实现起来比较简单,最终效果也与所给动画视频一致,但同时也有其固有的缺陷:首先是只有简单的特殊的动画效果可以使用此方案,原因在于其关键的部分在于使用 Matlab 提取动画的关键帧数据,这一操作只能对动画元素少、元素变换简单的动画实施;其次,如果动画效果有修改,则需要重新提取关键帧数据,这一点给动画的修改和调试带来不便;同时,如果设计师对动画有较大的修改,此方案也可能不再适用。

值得注意的是,苹果文档中还提到:如果应用不能及时提供显示帧,则应该降低帧率,因为较低的但是连贯的帧率要比高帧率但是存在掉帧看起来更顺滑一些。可以通过增大 frameInterval 这一属性的值来降低动画帧率。frameInterval 默认值为 1,表示每隔多少帧回调一次 selector。在没有卡顿时,iOS 设备屏幕显示每秒刷新60次,意味着 frameInterval 为默认值时,每秒回调60次 selector,当frameInterval 改为2时,每秒回调30(60/2)次 selector。

应用之帧率指示器

应用界面是否流畅是用户体验中十分重要的一方面,而帧率(FPS)是界面是否流畅的数字化指标,虽然可以通过 Instruments 查看到一些信息,但因操作路径较长,实际使用较少。

为了随时都可以直观的看到应用当前的帧率,可以给应用加一个帧率指示器。为了达到随时能看到的效果,我们把这个指示器放在一个特别的 Window 中,设置这个 Window 的 windowLevel 比应用中其他 Window 的 windowLevel 都要高。同时,为了减少对应用正常操作的影响,这个特别的 Window 只覆盖 statusBar 的一部分。

其实,苹果的官方文档中明确提到利用 CADisplaylink 可以计算显示的帧率:

The duration property provides the amount of time between frames. You can use this value in your application to calculate the frame rate of the display, the approximate time that the next frame will be displayed, and to adjust the drawing behavior so that the next frame is prepared in time to be displayed.

由上文可知正常情况下,duration 的值应该是1/60,但是当主线程被阻塞或者应用在刷新时没有在有限时间内完成必要的操作都会导致 duration 值的增加,通过每一帧的 duration 值即可计算出实际帧率。

此方案实现起来并不复杂,在Github中也可以找到很多类似实现,例如 RRFPSBar, 感兴趣的读者可自行前往查看。值得一提的是,帧率显示本身也会占用一定的资源并影响实际的帧率,所以不宜在实现中做过多的操作。

总结

CADisplaylink 与 NSTimer 非常类似,都可以以一定的时间间隔触发回调 selector,不同点在于 CADisplaylink 的时间间隔是与屏幕的刷新频率相关联的,这一点决定了 CADisplaylink 的应用多与显示有关。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,834评论 25 707
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,471评论 6 30
  • 人不能活的幻想的世界里,人处在这个社会,必然要融入这个社会。入乡随俗,如果你不去随俗,那么只能去出家,脱离世俗,否...
    勿忘心安karen阅读 220评论 0 0
  • 爱需要勇气与冒险,需要义无反顾的坚持,与安于平凡的气度。 虽需百转千回、经难涉险,但唯有爱,才是活这一遭最珍贵的事...
    小树的树洞阅读 702评论 0 0