項(xiàng)目里用到定時(shí)器時(shí),看同事是這么寫的:
@property (nonatomic,strong) dispatch_source_t timer;
if (!self.timer) {
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC));
uint64_t interval = (uint64_t)(1 * NSEC_PER_SEC);
dispatch_source_set_timer(self.timer, start, interval, 0);
dispatch_source_set_event_handler(self.timer, ^{
// NSLog(@"定時(shí)器開啟中........");
dispatch_async(dispatch_get_main_queue(), ^{
// 主線程添加事件處理
});
});
//啟動定時(shí)器
dispatch_resume(self.timer);
}
/**
* 移除定時(shí)器
*/
- (void)removeTimer {
if (self.timer) {
dispatch_source_cancel(self.timer);
self.timer = nil;
}
}
跟自己寫的NSTimer檔次不一樣,感覺這個(gè)逼格好高啊,然后就研究了下 dispatch_sourcer在定時(shí)器里的使用,如下。
定時(shí)器dispatch source定時(shí)產(chǎn)生事件,可以用來發(fā)起定時(shí)執(zhí)行的任務(wù),所有定時(shí)器dispatch source都是間隔定時(shí)器,一旦創(chuàng)建,會按你指定的間隔定期遞送事件。你需要為定時(shí)器dispatch source指定一個(gè)期望的定時(shí)器事件精度,也就是leeway值,讓系統(tǒng)能夠靈活地管理電源并喚醒內(nèi)核。例如系統(tǒng)可以使用leeway值來提前或延遲觸發(fā)定時(shí)器,使其更好地與其它系統(tǒng)事件結(jié)合。創(chuàng)建自己的定時(shí)器時(shí),你應(yīng)該盡量指定一個(gè)leeway值。
就算你指定leeway值為0,也不要期望定時(shí)器能夠按照精確的納秒來觸發(fā)事件。系統(tǒng)會盡可能地滿足你的需求,但是無法保證完全精確的觸發(fā)時(shí)間。
當(dāng)計(jì)算機(jī)睡眠時(shí),定時(shí)器dispatch source會被掛起,稍后系統(tǒng)喚醒時(shí),定時(shí)器dispatch source也會自動喚醒。根據(jù)你提供的配置,暫停定時(shí)器可能會影響定時(shí)器下一次的觸發(fā)。如果定時(shí)器dispatch source使用 dispatch_time 函數(shù)或DISPATCH_TIME_NOW 常量設(shè)置,定時(shí)器dispatch source會使用系統(tǒng)默認(rèn)時(shí)鐘來確定何時(shí)觸發(fā),但是默認(rèn)時(shí)鐘在計(jì)算機(jī)睡眠時(shí)不會繼續(xù)。
如果你使用dispatch_walltime函數(shù)來設(shè)置定時(shí)器dispatch source,則定時(shí)器會根據(jù)掛鐘時(shí)間來跟蹤,這種定時(shí)器比較適合觸發(fā)間隔相對比較大的場合,可以防止定時(shí)器觸發(fā)間隔出現(xiàn)太大的誤差。
下面是定時(shí)器dispatch source的一個(gè)例子,每30秒觸發(fā)一次,leeway值為1,因?yàn)殚g隔相對較大,使用 dispatch_walltime 來創(chuàng)建定時(shí)器。定時(shí)器會立即觸發(fā)第一次,隨后每30秒觸發(fā)一次。MyPeriodicTask 和 MyStoreTimer 是自定義函數(shù),用于實(shí)現(xiàn)定時(shí)器的行為,并存儲定時(shí)器到應(yīng)用的數(shù)據(jù)結(jié)構(gòu)。
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;
}
void MyCreateTimer()
{
dispatch_source_t aTimer = CreateDispatchTimer(30ull * NSEC_PER_SEC,
1ull * NSEC_PER_SEC,
dispatch_get_main_queue(),
^{ MyPeriodicTask(); });
// Store it somewhere for later use.
if (aTimer)
{
MyStoreTimer(aTimer);
}
}
雖然定時(shí)器dispatch source是接收時(shí)間事件的主要方法,你還可以使用其它選擇。如果想在指定時(shí)間間隔后執(zhí)行一個(gè)block,可以使用 dispatch_after 或 dispatch_after_f函數(shù)。這兩個(gè)函數(shù)非常類似于dispatch_async,但是只允許你指定一個(gè)時(shí)間值,時(shí)間一到就自動提交block到queue中執(zhí)行,時(shí)間值可以指定為相對或絕對時(shí)間。
然后我總結(jié)了下用dispatch_source寫定時(shí)器的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1、可以暫停,繼續(xù)。 不用像NSTimer一樣需要重新創(chuàng)建。
2、性能較好。
缺點(diǎn):
1、每次resume都會先執(zhí)行一次。
共同點(diǎn):
1、如果不手動釋放就不會走dealloc。
2、不精確