乐虎游戏|乐虎国际登录|欢迎你

iOS[QuartzCore框架]CADisplayLink篇

日期:2020-03-21编辑作者:计算机资讯

在学习CoreAnimation的时候,发现好多地方都用到了CADisplayLink,现在就整理下自己的笔记吧,不足之处敬请指正。======================================一、简介CADisplayLink简单的说就是一个定时器,每隔几毫秒刷新一次屏幕。CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器。我们在应用中创建一个新的CADisplayLink对象,把它添加到一个runloop中,并给它提供一个target和selector在屏幕刷新的时候调用。另外CADisplayLink 不能被继承。

在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法。在这个时候,我们就需要用到定时器。而关于定时器,ios开发我们会用到的也就以下几种。下面介绍以下:

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

二、NSTimer和CADisplayLink既然CADisplayLink也是一个定时器,那么两者有什么区别与联系呢?1、原理不同CADisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。CADisplayLink以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。NSTimer以指定的模式注册到runloop后,每当设定的周期时间到达后,runloop会向指定的target发送一次指定的selector消息。2、周期设置方式不同iOS设备的屏幕刷新频率是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的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。

1)、

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

三、CADisplayLink.h的常用属性和方法1、创建一个CADisplayLink对象+ (CADisplayLink *)displayLinkWithTarget:target selector:sel;2、将CADisplayLink对象添加到runloop中- addToRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode;3、将CADisplayLink对象从runloop中删除- removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode;4、结束CADisplayLink- invalidate;5、每帧之间的时间@property(readonly, nonatomic) CFTimeInterval duration;6、间隔多少帧调用一次selector 方法,默认1@property(nonatomic) NSInteger frameInterval;7、屏幕显示的上一帧的时间戳,只读的CFTimeInterval值。@property(readonly, nonatomic) CFTimeInterval timestamp;8、是否暂停,控制CADisplayLink的运行@property(getter=isPaused, nonatomic) BOOL paused;

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector userInfo:nil repeats:YES];

TimerInterval : 执行之前等待的时间。比如设置成1.0,就代表1秒后执行方法

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

四、注意1、通常来讲:iOS设备的刷新频率事60HZ也就是每秒60次。那么每一次刷新的时间就是1/60秒 大概16.7毫秒。当我们的frameInterval 值为1的时候我们需要保证的是 CADisplayLink调用的target的函数计算时间不应该大于 16.7否则就会出现严重的丢帧现象。 在mac应用中我们使用的不是CADisplayLink而是 CVDisplayLink它是基于C接口的用起来配置有些麻烦但是用起来还是很简单的。2、iOS并不能保证能以每秒60次的频率调用回调方法,这取决于:CPU的空闲程度如果CPU忙于其它计算,就没法保证以60HZ执行屏幕的绘制动作,导致跳过若干次调用回调方法的机会,跳过次数取决CPU的忙碌程度。执行回调方法所用的时间如果执行回调时间大于重绘每帧的间隔时间,就会导致跳过若干次回调调用机会,这取决于执行时间长短。

userInfo:可以写一些标识信息

2、周期设置方式不同iOS设备的屏幕刷新频率是60Hz,因此CADisplayLink的selector默认调用周期是每秒60次,这个周期可以通过frameInterval属性设置,CADisplayLink的selector每秒调用次数=60/frameInterval。比如当frameInterval设为2,每秒调用就变成30次。因此,CADisplayLink周期的设置方式略显不便。NSTimer的selector调用周期可以在初始化时直接设定,相对就灵活的多。

五、实例我们利用CAShapeLayer和贝塞尔曲线UIBezierPath还有CADisplayLink等实现一个弹性动画效果。demo地址:

target : 需要执行方法的对象。

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

图片 11451900088765490.gif1、 首先看下这个动画实现的逻辑思路图片 21451900102783370.png图中蓝色部分是一个CAShapeLayer,它的形状由UIBezierPath的路径组成。这个路径是有r1,r2,r3,r4,r5这5个红点确定。其中r1,r2,r3,r4都是不动点,唯一可以动的是r5点。根据动态图可以看出CAShapeLayer的形状是随着r5红点的移动而相应变化的,所以只要获得r5的坐标变化就可以用UIBezierPath做出相应的路径,然后就可以形成相应的形状。2、实现初始化CAShapeLayer图片 3屏幕快照 2016-05-31 下午5.32.52.png初始化r5点图片 4FC4FCE6D-2A16-4734-ABA7-7FA45CFFFFE5.png添加移动手势&CADisplayLink图片 5AA778F29-0933-4C82-B1BB-1CBD8D794E9E.png手势解析手势移动时,r5红点跟着手势移动,_shapeLayer则根据r5的坐标来扩大自己的区域手势结束时,r5红点通过UIView的动画方法来改变r5的坐标,同时_shapeLayer根据r5的坐标缩小自己的区域并最终返回原形。图片 609EB9484-BB8F-41B6-B5F2-3ECD70763731.png根据r5的位置,更新_shapeLayer形状图片 70AA97B2F-D1A2-4CFE-92C5-F8EA1F8FE1F7.png计算弹簧效果坐标图片 82AF1A988-8FFF-472A-BC4E-DD96C5679C73.png感谢:

selector : 需要执行的方法

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

repeats : 是否需要循环

4、使用场合从原理上不难看出,CADisplayLink使用场合相对专一,适合做界面的不停重绘,比如视频播放的时候需要不停地获取下一帧用于界面渲染。NSTimer的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。

2)、

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

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {

}];

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。

TimerInterval : 执行之前等待的时间。比如设置成1.0,就代表1秒后执行方法

3、timestamp只读的CFTimeInterval值,表示屏幕显示的上一帧的时间戳,这个属性通常被target用来计算下一帧中应该显示的内容。虽然名为时间戳,但这和常见的unix时间戳差异很大,事实上这是CoreAnimation使用的时间格式。每个CALayer都有一个本地时间,可以获取当前CALayer的本地时间并打印:

repeats : 是否需要循环

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

使用block的方法就直接在block里面写延时后要执行的代码就可以了

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

3)、

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

本文由乐虎游戏发布于计算机资讯,转载请注明出处:iOS[QuartzCore框架]CADisplayLink篇

关键词:

【LX豪彩】UIProgressView进程条的性格介绍

- viewDidLoad { - (void)viewDidLoad { [super viewDidLoad]; //实例化一个进度条,有两种样式,一种是UIProgressViewStyleBar一种是UIPro...

详细>>

iOS动漫之自定义转场动漫(push卡塔尔国

push.gif iOS7 开始苹果推出了自定义转场的 API 。从此,任何可以用 CoreAnimation实现的动画,都可以出现在两个 ViewContr...

详细>>

Git使用简析

推送本地操作 初始化一个本地Git仓库,在需要添加版本控制的文件夹根目录中使用gitinit命令。 添加文件到本地Git仓...

详细>>

如何在移动开发者的寒冬中破冰而出?

世家好,好像有那么几天没写小说了,重要是近日一向很忙,没什么时间放平心态写。 在这里个行业,每间隔一段时...

详细>>