学习参考了:
http://www.jianshu.com/p/c35a81c3b9eb
https://zsisme.gitbooks.io/ios-/content/chapter11/frame-timing.html

自己总结一下,方便以后使用

NSTimer

iOS按照每秒60次刷新屏幕,然后CAAnimation计算出需要展示的新的帧,然后在每次屏幕更新的时候同步绘制上去,CAAnimation最机智的地方在于每次刷新需要展示的时候去计算插值和缓冲。

   NSTimer是如何工作的。

iOS上的每个线程都管理了一个NSRunloop,字面上看就是通过一个循环来完成一些任务列表。但是对主线程,这些任务包含如下几项:

  • 处理触摸事件
  • 发送和接受网络数据包
  • 执行使用gcd的代码
  • 处理计时器行为
  • 屏幕重绘

当你设置一个NSTimer,他会被插入到当前任务列表中,然后直到指定时间过去之后才会被执行。但是何时启动定时器并没有一个时间上限,而且它只会在列表中上一个任务完成之后开始执行。这通常会导致有几毫秒的延迟,但是如果上一个任务过了很久才完成就会导致延迟很长一段时间。

屏幕重绘的频率是一秒钟六十次,但是和定时器行为一样,如果列表中上一个执行了很长时间,它也会延迟。这些延迟都是一个随机值,于是就不能保证定时器精准地一秒钟执行六十次。有时候发生在屏幕重绘之后,这就会使得更新屏幕会有个延迟,看起来就是动画卡壳了。有时候定时器会在屏幕更新的时候执行两次,于是动画看起来就跳动了。

通过一些途径来优化:

  • 我们可以用CADisplayLink让更新频率严格控制在每次屏幕刷新之后。
  • 基于真实帧的持续时间而不是假设的更新频率来做动画。
  • 调整动画计时器的run loop模式,这样就不会被别的事件干扰。

CADisplayLink:

总是在屏幕完成一次更新之前启动,它的接口设计的和NSTimer很类似,所以它实际上就是一个内置实现的替代,但是和timeInterval以秒为单位不同,CADisplayLink有一个整型的frameInterval属性,指定了间隔多少帧之后才执行。默认值是1,意味着每次屏幕更新之前都会执行一次。但是如果动画的代码执行起来超过了六十分之一秒,你可以指定frameInterval为2,就是说动画每隔一帧执行一次(一秒钟30帧)或者3,也就是一秒钟20次,等等。

CADisplayLink而不是NSTimer,会保证帧率足够连续,使得动画看起来更加平滑,但即使CADisplayLink也不能保证每一帧都按计划执行,一些失去控制的离散的任务或者事件(例如资源紧张的后台程序)可能会导致动画偶尔地丢帧。当使用NSTimer的时候,一旦有机会计时器就会开启,但是CADisplayLink却不一样:如果它丢失了帧,就会直接忽略它们,然后在下一次更新的时候接着运行。

计算帧的持续时间:

CACurrentMediaTime()记录当前时间,然后和上一帧记录的时间去比较。得到真实的每帧持续的时间,然后代替硬编码的六十分之一秒,来更新UI。

Run Loop和Run Loop模式:

对于run loop来说,我们就使用了主线程的run loop,因为任何用户界面的更新都需要在主线程执行,但是模式的选择就并不那么清楚了,每个添加到run loop的任务都有一个指定了优先级的模式,为了保证用户界面保持平滑,iOS会提供和用户界面相关任务的优先级,而且当UI很活跃的时候的确会暂停一些别的任务。

一个典型的例子就是当是用UIScrollview滑动的时候,重绘滚动视图的内容会比别的任务优先级更高,所以标准的NSTimer和网络请求就不会启动,一些常见的run loop模式如下:

  • NSDefaultRunLoopMode - 标准优先级
  • NSRunLoopCommonModes - 高优先级
  • UITrackingRunLoopMode - 用于UIScrollView和别的控件的动画

用了NSDefaultRunLoopMode,但是不能保证动画平滑的运行,所以就可以用NSRunLoopCommonModes来替代。但是要小心,因为如果动画在一个高帧率情况下运行,你会发现一些别的类似于定时器的任务或者类似于滑动的其他iOS动画会暂停,直到动画结束。

同样可以同时对CADisplayLink指定多个run loop模式,于是我们可以同时加入NSDefaultRunLoopModeUITrackingRunLoopMode来保证它不会被滑动打断,也不会被其他UIKit控件动画影响性能,像这样:

self.timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step:)];
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode];

CADisplayLink类似,NSTimer同样也可以使用不同的run loop模式配置,通过别的函数,而不是+scheduledTimerWithTimeInterval:构造器

self.timer = [NSTimer timerWithTimeInterval:1/60.0
target:self
selector:@selector(step:)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer
forMode:NSRunLoopCommonModes];

定时帧:NSTimer和CADisplayLink的更多相关文章

  1. iOS:三种常见计时器(NSTimer、CADisplayLink、dispatch_source_t)的使用

    一.介绍 在iOS中,计时器是比较常用的,用于统计累加数据或者倒计时等,例如手机号获取验证码.计时器大概有那么三种,分别是:NSTimer.CADisplayLink.dispatch_source_ ...

  2. iOS 定时器 NSTimer、CADisplayLink、GCD3种方式的实现

    在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法.在这个时候,我们就需要用到定时器. 然而,在iOS中有很多方法完成以上的任务,到底有多少种方法呢?经过查阅资 ...

  3. iOS定时器-- NSTimer 和CADisplaylink

    iOS定时器-- NSTimer 和CADisplaylink 一.iOS中有两种不同的定时器: 1.  NSTimer(时间间隔可以任意设定,最小0.1ms)// If seconds is les ...

  4. NSTimer、CADisplayLink、GCD 三种定时器的用法 —— 昉

    在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法.在这个时候,我们就需要用到定时器. 在iOS中有很多方法完成定时器的任务,例如 NSTimer.CADisp ...

  5. 定时器 NSTimer 和 CADisplayLink

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

  6. NSTimer、CADisplayLink 内存泄漏

    NSTimer.CADisplayLink 内存泄漏 内存泄漏的原因 CADisplayLink 要用 Taget 和 Selector 初始化,NSTimer 也可以用类似的方法初始化.这样初始化之 ...

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

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

  8. IOS NSTimer和CADisplayLink的用法

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

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

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

随机推荐

  1. .NET中 类型,对象,线程栈,托管堆在运行时的关系

    .NET中 类型,对象,线程栈,托管堆在运行时的关系 The Relationship at Run Time between Types,Objects,A Thread's Stack,and T ...

  2. 分享.net常见的内存泄露及解决方法

    分享.net常见的内存泄露及解决方法 关于内存泄漏的问题,之前也为大家介绍过,比如:<C++中内存泄漏的检测方法介绍>,是关于C++内存泄漏的.今天为大家介绍的是关于.NET内存泄漏的问题 ...

  3. 【OpenMesh】使用迭代器和循环机

    原文出处: http://openmesh.org/Documentation/OpenMesh-Doc-Latest/tutorial.html 这个例子展现: 如何使用迭代器 如何使用循环机 这个 ...

  4. thinkpad x230i U盘启动

    现在的thinkpad的笔记本真麻烦,设置个U盘启动都不好使,网上找了好多都不管用,后来打电话问的售后电话才搞定,具体步骤如下: 按F1进bios的 [Security]中最下面Secure Boot ...

  5. Ext JS4百强应用: 用grid.plugin.CellEditing做高级查询 --第10强

    Ext JS4,用grid.plugin.CellEditing做高级查询: 写了90%,界面出来了,小兴奋就贴出来,还有细节要调整,基本能用. 代码: Ext.define('chenghao.ad ...

  6. Java 和 IOS 区别

    Java接口与Objective-C正式协议类似,因为都需要实现     一组方法.Java具有抽象类,但Objective-C没有.Java具有类变量,但Objective-C中,可以使用文件范围内 ...

  7. are both mapped to the url-pattern 错误解决方法

    今天运行tomcat的时候出现报了一大波错误,下面我截取了部分错误信息: 严重:A child container failed during start java.util.concurrent.E ...

  8. Maven3在Eclipse上安装插件

    eclipse 安装插件的方式最常见的有两种: 1. 一种是在线安装,这貌似是用的最多的,就是:Help -->  Install New Software,然后输入 HTTP 地址来安装,但有 ...

  9. 百度地图API的自动定位路线查询

    功能如下:打开时自动定位到当前位置(浏览器可能会屏蔽自动定位功能,建议手机查看,或直接打开地址:http://1.jingcode.applinzi.com/test2.html),输入目的地点击搜索 ...

  10. SASS使用CSS3动画并使动画暂停和停止在最后一帧的简单例子

    今天在手机上试了试这个 css3 动画效果,可以把动画效果停留在最后一帧上,以及鼠标 :hover 暂停动画,比较实用的功能,不用 JS 也能实现这些效果了. 不过测试体验感觉手机上没有 jQuery ...