群里有人提到這個(gè),各種抱怨NSTimer在runloop下的問題智末,還有內(nèi)存問題枫笛,有人提到可以用GCD做倒計(jì)時(shí)卒废,上網(wǎng)查了下寫了個(gè)demo沛厨,這里記錄下:
重點(diǎn)API:DispatchSourceTimer
這個(gè)協(xié)議是沒有init的,初始化方法是DispatchSource.makeTimerSource()
setEventHandler:這個(gè)不說了摔认,直接在closure里寫執(zhí)行代碼
cancel():停止
scheduleRepeating(deadline:interval:) :暫時(shí)只看了這一個(gè)schedule方法逆皮,其他的還沒看,第一個(gè)參數(shù)是開始時(shí)間参袱,可以直接.now()电谣,第二個(gè)參數(shù)是間隔。
resume:開始計(jì)時(shí)
直接上正確代碼
基本用法說完了蓖柔,下面說一下內(nèi)存問題辰企,GCD的這個(gè)計(jì)時(shí)器的內(nèi)存問題實(shí)在太干凈了,和NSTimer那個(gè)在runloop上面跑的又有循環(huán)引用問題的妖艷賤貨不一樣况鸣。
注意看上面的t的內(nèi)存釋放問題牢贸,大家知道在ARC里,棧幀內(nèi)存在方法執(zhí)行完之后會釋放掉镐捧,里面的臨時(shí)變量都會釋放潜索,這里的t變量很明顯就是個(gè)純的臨時(shí)變量臭增,但是t自己的closure里引用了t自己,所以在這段代碼的方法執(zhí)行完之后竹习,t不會立即釋放誊抛,會等到eventHandler釋放之后再釋放,完美整陌!
如果把這一句t.cancel()去掉拗窃,那么在外部代碼執(zhí)行完之后t會立即釋放,t釋放之后自然eventHandler也不會繼續(xù)跑了泌辫,這一點(diǎn)在使用的時(shí)候要注意随夸。
那么如果在closure里不需要引用這個(gè)t而且又不想讓t提前釋放怎么辦呢?
提升作用域嘛震放,最簡單的話加一個(gè)self.t = t就行了宾毒。
6月20日更新
發(fā)現(xiàn)一個(gè)問題,那就是默認(rèn)在執(zhí)行timer的handler的時(shí)候殿遂,不是在主線程中的U╊酢!如果在計(jì)時(shí)過程中有涉及UI相關(guān)的刷新墨礁,務(wù)必加上DispatchQueue.main.async幢竹。