Dispatch Source Timer的使用及注意事項(xiàng)介紹
前言
Dispatch Source Timer 是一種與 Dispatch Queue 結(jié)合使用的定時(shí)器。當(dāng)需要在后臺 queue 中定期執(zhí)行任務(wù)的時(shí)候,使用 Dispatch Source Timer 要比使用 NSTimer 更加自然,也更加高效(無需在 main queue 和后臺 queue 之前切換)。下面將詳細(xì)給大家介紹關(guān)于Dispatch Source Timer的使用和一些注意事項(xiàng),話不多說了,來一起看看詳細(xì)的介紹吧。
創(chuàng)建 Timer
Dispatch Source Timer 首先其實(shí)是 Dispatch Source 的一種,關(guān)于 Dispatch Source 的內(nèi)容在這里就不再贅述了。下面是蘋果官方文檔里給出的創(chuàng)建 Dispatch Timer 的代碼:
dispatch_source_t CreateDispatchTimer(uint64_t interval,
uint64_t leeway,
dispatch_queue_t queue,
dispatch_block_t block)
{
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
0, 0, queue);
if (timer)
{
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
}
return timer;
}
有幾個(gè)地方需要注意:
- Dispatch Source Timer 是間隔定時(shí)器,也就是說每隔一段時(shí)間間隔定時(shí)器就會觸發(fā)。在 NSTimer 中要做到同樣的效果需要手動(dòng)把 repeats 設(shè)置為 YES。
- dispatch_source_set_timer 中第二個(gè)參數(shù),當(dāng)我們使用dispatch_time 或者 DISPATCH_TIME_NOW 時(shí),系統(tǒng)會使用默認(rèn)時(shí)鐘來進(jìn)行計(jì)時(shí)。然而當(dāng)系統(tǒng)休眠的時(shí)候,默認(rèn)時(shí)鐘是不走的,也就會導(dǎo)致計(jì)時(shí)器停止。使用 dispatch_walltime 可以讓計(jì)時(shí)器按照真實(shí)時(shí)間間隔進(jìn)行計(jì)時(shí)。
- dispatch_source_set_timer 的第四個(gè)參數(shù) leeway 指的是一個(gè)期望的容忍時(shí)間,將它設(shè)置為 1 秒,意味著系統(tǒng)有可能在定時(shí)器時(shí)間到達(dá)的前 1 秒或者后 1 秒才真正觸發(fā)定時(shí)器。在調(diào)用時(shí)推薦設(shè)置一個(gè)合理的 leeway 值。需要注意,就算指定 leeway 值為 0,系統(tǒng)也無法保證完全精確的觸發(fā)時(shí)間,只是會盡可能滿足這個(gè)需求。
- event handler block 中的代碼會在指定的 queue 中執(zhí)行。當(dāng) queue 是后臺線程的時(shí)候,dispatch timer 相比 NSTimer 就好操作一些了。因?yàn)?NSTimer 是需要 Runloop 支持的,如果要在后臺 dispatch queue 中使用,則需要手動(dòng)添加 Runloop。使用 dispatch timer 就簡單很多了。
- dispatch_source_set_event_handler 這個(gè)函數(shù)在執(zhí)行完之后,block 會立馬執(zhí)行一遍,后面隔一定時(shí)間間隔再執(zhí)行一次。而 NSTimer 第一次執(zhí)行是到計(jì)時(shí)器觸發(fā)之后。這也是和 NSTimer 之間的一個(gè)顯著區(qū)別。
停止 Timer
停止 Dispatch Timer 有兩種方法,一種是使用 dispatch_suspend,另外一種是使用 dispatch_source_cancel。
dispatch_suspend 嚴(yán)格上只是把 Timer 暫時(shí)掛起,它和 dispatch_resume 是一個(gè)平衡調(diào)用,兩者分別會減少和增加 dispatch 對象的掛起計(jì)數(shù)。當(dāng)這個(gè)計(jì)數(shù)大于 0 的時(shí)候,Timer 就會執(zhí)行。在掛起期間,產(chǎn)生的事件會積累起來,等到 resume 的時(shí)候會融合為一個(gè)事件發(fā)送。
需要注意的是:dispatch source 并沒有提供用于檢測 source 本身的掛起計(jì)數(shù)的 API,也就是說外部不能得知一個(gè) source 當(dāng)前是不是掛起狀態(tài),在設(shè)計(jì)代碼邏輯時(shí)需要考慮到這一點(diǎn)。
dispatch_source_cancel 則是真正意義上的取消 Timer。被取消之后如果想再次執(zhí)行 Timer,只能重新創(chuàng)建新的 Timer。這個(gè)過程類似于對 NSTimer 執(zhí)行 invalidate。
關(guān)于取消 Timer,另外一個(gè)很重要的注意事項(xiàng):dispatch_suspend 之后的 Timer,是不能被釋放的!下面的代碼會引起崩潰:
- (void)stopTimer
{
dispatch_suspend(_timer);
_timer = nil; // EXC_BAD_INSTRUCTION 崩潰
}
因此使用 dispatch_suspend 時(shí),Timer 本身的實(shí)例需要一直保持。使用 dispatch_source_cancel 則沒有這個(gè)限制:
- (void)stopTimer
{
dispatch_source_cancel(_timer);
_timer = nil; // OK
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
ios開發(fā)加載webview顯示進(jìn)度條實(shí)例
本篇文章主要介紹了ios開發(fā)加載webview顯示進(jìn)度條實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
IOS開發(fā)之多線程N(yùn)SThiread GCD NSOperation Runloop
這篇文章主要介紹了IOS多線程開發(fā),主要用到NSThiread、GCD、 NSOperation、Runloop,有詳細(xì)的原理解析和實(shí)例代碼,對多線程感興趣的同學(xué),可以參考下2021-04-04
iOS 解決UICollectionView 計(jì)算 Cell 大小的問題
本文主要介紹iOS UICollectionView,這里給大家一個(gè)實(shí)例代碼作為參考,并指出經(jīng)常遇到的問題和解決辦法,希望能幫助有需要的小伙伴2016-07-07
詳解iOS應(yīng)用開發(fā)中使用設(shè)計(jì)模式中的抽象工廠模式
這篇文章主要介紹了iOS應(yīng)用開發(fā)中使用設(shè)計(jì)模式中的抽象工廠模式,示例代碼為傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-03-03
iOS WKWebview 白屏檢測實(shí)現(xiàn)的示例
這篇文章主要介紹了iOS WKWebview 白屏檢測實(shí)現(xiàn)的示例,幫助大家更好的進(jìn)行ios開發(fā),感興趣的朋友可以了解下2020-10-10

