工作需要,粗略了解了ios上的幾種定時器。

NSTimer:
? ? ? ? ? ?這個底層怎么定時我不清楚,應該是到了一定時間之后,向runLoop添加一個事件,這也就意味著,如果想在異步線程開啟timer ,就需要手動的將timer 添加到runLoop中,并且run起來。
? ? ? ? ? ?網(wǎng)上看了一些說的精確度,不是明白,親測過,子線程創(chuàng)建一個timer,runLoop run起來,只要timer里面的事件,不超過timer定時的時間,timer定時還是很準確的,所以如果項目需要,timer里面的執(zhí)行事件的時間超過了定時器的時間,就會出問題了(試想一下,即使把事件再拿到另外一個線程去執(zhí)行,執(zhí)行時間永遠都是大于定時時間的,即使不影響定時時間,那么事件處理的堆積事件就會越來越多,肯定無法滿足需求,所以最好的是,將事件拆分,做成多個管道,多個定時器,定時器時間大于處理定時器事件的時間)。我們通常說的timer會出問題,我猜想可能是在主線程定義了一個timer,runloop執(zhí)行一個耗時很長的循環(huán),錯過了timer的周期,這肯定會出問題,還有就是timer里面的事件處理時間不夠也會出問題。所以我的解決辦法是,子線程runLoop run起來,保持線程,同時保證timer里面的事件處理時間不超過timer時間,這樣就ok了。
? ? ? ? ? 綜上所訴,用處理一般的事件完全足夠,只是使用中需要注意。
CADisplayLink:
? ? ? ? ? 這個是根據(jù)屏幕的幀率來發(fā)送事件,也依賴于runLoop,也就是說,我們只能控制多少幀,觸發(fā)我們定義的事件,可用于界面的刷新,不能隨心所欲的控制時間,不滿足我們一般的需求。使用也很簡單,自行看API
GCD的source timer:
? ? ? 個人覺得這是比較給力(原諒我詞匯的匱乏)的一個定時器了。原因如下,它不依賴于runLoop,底層兩個隊列,一個事件隊列,一個任務隊列,定時到了之后,從任務隊列里取出事件,加入到事件隊列(之前還有一步,向任務隊列push任務),執(zhí)行事件,至于他的一直執(zhí)行(為什么不依賴于runLoop,這于GCD的底層實現(xiàn)有關,有興趣可以自行了解),放到一個子線程執(zhí)行(想在主線程執(zhí)行的,可以用mainQUeue包一層),在子線程的執(zhí)行順序也是串行的,所以如果block的執(zhí)行事件時間大于定時時間,還是會阻塞,可以一定層度上解決,請看下面代

可以在block塊里再用一個隊列,異步執(zhí)行,包起來,但是我們看一下執(zhí)行結果

確實,執(zhí)行事件表面看并沒有影響定時器的定時,但是注意看始終都是系統(tǒng)分配的幾個線程去執(zhí)行事件,也就是說這幾個線程是重復利用的,當?shù)谝淮问褂猛?,第二次使用的時候,定時并不準確(可能是線程清理需要事件,具體不清楚),還有定時器的定時還是不準確,這可能就跟GCDSource內(nèi)部實現(xiàn)有關系了,所以不推薦這樣使用,目前我個人的想法就是,如果事件處理時間過長,要嗎想辦法拆分事件,加管道,加定時器,要嗎延長定時時間。
與timer相比,的優(yōu)勢就是,不需要維持runLoop,(性能消耗上或許有區(qū)別,沒有實際看過),還有本身就是子線程去執(zhí)行的,不會阻塞主線程。
以上只是我個人的想法和總結,肯定有說得不對的地方,希望多討論,多批評指正。