關(guān)于GCD Timer的重點(diǎn)注意事項(xiàng)

#import "GCDTimer.h"

@interface GCDTimer ()

@property (nonatomic, strong) dispatch_source_t timer;

@end

@implementation ?GCDTimer

- (void)runTimer?

? ? self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());

? ? dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), (uint64_t)(3*NSEC_PER_SEC), 0);

? ? dispatch_source_set_event_handler(self.timer, ^{

? ? ? ? NSLog(@"dispatch");

? ? });

? ? dispatch_resume(self.timer);

}

- (void)dealloc{

? ? dispatch_source_cancel(_timer);

}

@end

dispatch_resume()

激活源對(duì)象。新創(chuàng)建的timer必須激活才會(huì)執(zhí)行。

dispatch_suspend()

暫停源對(duì)象。dispatch_suspend 暫停隊(duì)列并不意味著當(dāng)前執(zhí)行的 block 暫停,調(diào)用 dispatch_suspend 暫停一個(gè)隊(duì)列,并不意味著暫停當(dāng)前正在執(zhí)行的 block,而是 block 可以執(zhí)行完,但是接下來的 block 會(huì)被暫停,直到 dispatch_resume 被調(diào)用。

dispatch_source_cancel()

銷毀定時(shí)器。dispatch_source_cancel 則是真正意義上的取消?timer。被取消之后如果想再次執(zhí)行?timer,只能重新創(chuàng)建新的?timer。這個(gè)過程類似于對(duì) NSTimer 執(zhí)行 invalidate。

需要注意的是,dispatch_source_t? 一定要被設(shè)置為成員變量,否則將會(huì)立即被釋放。

注意:暫停(dispatch_suspend)的timer,不能被釋放的,會(huì)引起崩潰。

Calls to dispatch_suspend() must be balanced with calls to dispatch_resume().

dispatch_suspend 和 dispatch_resume 應(yīng)該是成對(duì)出現(xiàn)的。兩者分別會(huì)減少和增加 dispatch 對(duì)象的暫停計(jì)數(shù),但是沒有 API 獲取當(dāng)前是暫停還是執(zhí)行狀態(tài),所以需要自己記錄。你調(diào)用了suspend(暫停)幾次,你想resume(恢復(fù))的話,就必須要remuse(恢復(fù))幾次,才能繼續(xù)運(yùn)行。

所以建議控制器添加一個(gè)標(biāo)識(shí)符,記錄源是否處于暫停狀態(tài),在dealloc事件中判斷當(dāng)前源是否被暫停,如果被暫停,則resume,即可解決內(nèi)存泄漏問題。

但是還有不一般的情況,如果暫停的代碼加到 dispatch_source_set_event_handler 的 block 中,并不會(huì)發(fā)生崩潰,但是這個(gè)時(shí)候頁面會(huì)無法釋放造成內(nèi)存泄漏。

dispatch_source_set_event_handler(timer, ^() {

? dispatch_suspend(self.timer);

});

其他注意事項(xiàng):

1.但remuse(恢復(fù))的狀態(tài)下,如果再進(jìn)行一次resume(恢復(fù))就會(huì)crash,所以要注冊(cè)一個(gè)BOOL值的狀態(tài)進(jìn)行記錄,防止多次suspend和resume引起閃退。

2.在suspend(暫停)的狀態(tài)下,如果你設(shè)置timer = nil就會(huì)crash。

3.在suspend(暫停)的狀態(tài)下,即使調(diào)用dispatch_source_cancel也沒用,會(huì)造成內(nèi)存泄漏,甚至崩潰。

后記:

GCDTimer的優(yōu)勢(shì):不受當(dāng)前runloopMode的影響。

劣勢(shì):其計(jì)時(shí)效應(yīng)仍不是百分之百準(zhǔn)確的。另外,他的觸發(fā)事件也有可能被阻塞,當(dāng)GCD內(nèi)部管理的所有線程都被占用時(shí),其觸發(fā)事件將被延遲

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容