内容简介:项目中有定时刷新的功能需求,使用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 :
我们再看看代码,循环引用、计时不准确、线程问题都得到了解决,相比较除了代码量稍微多一些,在精度方面无疑是最好的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 各种定时器--最全的定时器使用
- java定时器无法自动注入的问题解析(原来Spring定时器可以这样注入service)
- Golang定时器陷阱
- jmeter(七)定时器
- iOS定时器使用
- iOS定时器相关实践
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。