设计一个简单准确的定时器

栏目: IT技术 · 发布时间: 4年前

内容简介:项目中有定时刷新的功能需求,使用timer 会强引用 target,而 target 又强引用者 timer 对象,最后就会导致当前 viewcontroller 不会被释放,deinit 方法也不会被调用,从而产生了循环引用。

项目中有定时刷新的功能需求,使用 NSTimer 一把梭之后发现了如下的问题,我们首先写一段示例代码:

设计一个简单准确的定时器

1.循环引用

timer 会强引用 target,而 target 又强引用者 timer 对象,最后就会导致当前 viewcontroller 不会被释放,deinit 方法也不会被调用,从而产生了循环引用。

第一种可以通过 Timer 的另一个方法,不去使用 target,在 block 中弱引用 self,可以解决循环引用的问题,代码如下。

设计一个简单准确的定时器

第二种方式可以通过引入一个中间对象,让 target 强引用中间对象,中间对象在弱引用 timer,这样一旦 viewcontroller 被释放掉,deinit 方法就会被调用,timer 就会被释放掉。但是这样存在一个问题是,中间对象其实是无法响应 selector,会导致崩溃。这样就是需要用到消息转发机制,将所有中间对象收到的事件都转发给 self.target 进行响应,代码如下。

主类的代码:

设计一个简单准确的定时器

中间对象 MyProxy 的代码:

设计一个简单准确的定时器

其他还有些方式,可以看看这篇博客 iOS之NSTimer循环引用的解决方案 - 掘金 ,这边不做详细介绍了。

2.Runloop 导致计时不准确

由于 NSTimer 是依赖于 RunLoop 机制的,所以会因为 Runloop 的问题导致计时不准确。上面两个 Timer.scheduledTimer 初始化方法都是默认运行在 Runloop 的 default mode 中。

在 ScrollView 在滑动的过程中,主线程的 Runloop 会切换到 UITrackingRunLoopMode ,这个时候 timer 就不会运行,就会导致计时不准确。如果想要滑动的时候不失效,可以将 timer 运行在 NSRunLoopCommonModes

3.线程问题

同样由于 NSTimer 是依赖于 RunLoop 机制的,所以在子线程中初始化一个 timer 默认是不会运行的。原因是因为子线程并没有创建 Runloop。

CADisplayLink

官方文档对于 CADisplayLink 的介绍是:

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

一般情况下,我们的屏幕刷新率是1/60s 一次。CADisplayLink 跟 NSTimer 的用法基本相似,NSTimer 的时间间隔是以秒为单位,而 CADisplayLink 是使用帧率来作为时间间隔的单位。

所以说 CADisplayLink 最常见到的应用场景就是写一个监测 FPS 的工具,我这里引用 YYFPSLabel 的代码实现大概介绍下原理:

设计一个简单准确的定时器

我们可以看到,使用方法与 NSTimer 基本一致,同样是使用了 YYWeakProxy 来避免循环引用,且 CADisplayLink 还需要手动添加到 Runloop 中。那么问题在哪里?问题就出在 CADisplayLink 仍然是基于 Runloop 来实现的,而 RunLoop 的运行取决于其所在的 mode 以及 CPU 的繁忙程度,当 CPU 忙于计算显示内容或者 GPU 工作太繁重时,就会导致显示出来的 FPS 与 Instrument 的不一致。所以说基于CADisplayLink实现的 FPS 无法完全检测出当前 Core Animation 的性能情况,它只能检测出当前 RunLoop 的帧率。

GCD

最后我们说到今天的重点,通过 GCD 来实现 Timer,主要是使用 DispatchSource 。步骤如下:创建一个监听的事件类型对应的 dispatch source,然后给这个 source 指定闭包和 Dispatch Queue。当 source 监听到相应的事件时,就会将该闭包自动加到 queue 中执行。代码如下,引用自 GitHub - 100mango/SwiftTimer: Simple and Elegant Timer

设计一个简单准确的定时器

我们再看看代码,循环引用、计时不准确、线程问题都得到了解决,相比较除了代码量稍微多一些,在精度方面无疑是最好的。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python 3学习笔记(上卷)

Python 3学习笔记(上卷)

雨痕 / 电子工业出版社 / 2018-1 / 89

经过9 年的发展,Python 3 生态已相当成熟。无论是语言进化、解释器性能提升,还是第三方支持,都是如此。随着Python 2.7 EOF 日趋临近,迁移到Python 3 的各种障碍也被逐一剔除。是时候在新环境下学习或工作了。 人们常说Python 简单易学,但这是以封装和隐藏复杂体系为代价的。仅阅读语言规范很难深入,亦无从发挥其应有能力,易学难精才是常态。《Python 3学习笔记(......一起来看看 《Python 3学习笔记(上卷)》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具