群里有人提到这个,各种抱怨NSTimer在runloop下的问题,还有内存问题,有人提到可以用GCD做倒计时,上网查了下写了个demo,这里记录下:
重点API:DispatchSourceTimer
这个协议是没有init的,初始化方法是DispatchSource.makeTimerSource()
setEventHandler:这个不说了,直接在closure里写执行代码
cancel():停止
scheduleRepeating(deadline:interval:) :暂时只看了这一个schedule方法,其他的还没看,第一个参数是开始时间,可以直接.now(),第二个参数是间隔。
resume:开始计时
直接上正确代码
正确的demo基本用法说完了,下面说一下内存问题,GCD的这个计时器的内存问题实在太干净了,和NSTimer那个在runloop上面跑的又有循环引用问题的妖艳贱货不一样。
注意看上面的t的内存释放问题,大家知道在ARC里,栈帧内存在方法执行完之后会释放掉,里面的临时变量都会释放,这里的t变量很明显就是个纯的临时变量,但是t自己的closure里引用了t自己,所以在这段代码的方法执行完之后,t不会立即释放,会等到eventHandler释放之后再释放,完美!
如果把这一句t.cancel()去掉,那么在外部代码执行完之后t会立即释放,t释放之后自然eventHandler也不会继续跑了,这一点在使用的时候要注意。
那么如果在closure里不需要引用这个t而且又不想让t提前释放怎么办呢?
提升作用域嘛,最简单的话加一个self.t = t就行了。
6月20日更新
发现一个问题,那就是默认在执行timer的handler的时候,不是在主线程中的!!如果在计时过程中有涉及UI相关的刷新,务必加上DispatchQueue.main.async。
网友评论