封裝GCD定時(shí)器

在開發(fā)過程中,對(duì)于定時(shí)器相信大家都不陌生,在http://www.lxweimin.com/p/0194a0866872 這篇文章中,我有談過各種定時(shí)器的優(yōu)缺點(diǎn),這里就簡(jiǎn)單封裝一個(gè)實(shí)用的不依賴于RunLoop運(yùn)行模式的GCD定時(shí)器

  • 首先GCD定時(shí)器本質(zhì)也是對(duì)象必須有一個(gè)強(qiáng)引用應(yīng)用著,不然就會(huì)被釋放,由于提供的是類方法,就定義一個(gè)全局靜態(tài)變量字典來保存timer對(duì)象

//存放timer對(duì)象
static NSMutableDictionary *timerDictionary;
//根據(jù)index來存儲(chǔ)不同的timer對(duì)象
static NSInteger timerIndex = 0;

- 提供了一下兩個(gè)類方法來初始化定時(shí)器,區(qū)別在于第一個(gè)初始化完成后自動(dòng)開啟定時(shí)器,第二個(gè)需要自己選擇開啟與否


//初始化定時(shí)器,默認(rèn)初始化完成后開啟

  • (void)timerWithTimeInterval:(NSTimeInterval)timeInterval dispatchQueue:(dispatch_queue_t)dispatchQueue withBlock:(void(^)(XHR_dispatch_timer *))block;

//初始化定時(shí)器,需要手動(dòng)開啟

  • (void)timerWithTimeInterval:(NSTimeInterval)timeInterval dispatchQueue:(dispatch_queue_t)dispatchQueue isOn:(BOOL)isOn withBlock:(void(^)(XHR_dispatch_timer *))block;
- 具體方法的實(shí)現(xiàn)如下
  

//初始化定時(shí)器

  • (void)timerWithTimeInterval:(NSTimeInterval)timeInterval dispatchQueue:(dispatch_queue_t)dispatchQueue withBlock:(void (^)())block
    {
    //默認(rèn)方法自動(dòng)開啟定時(shí)器
    [self timerWithTimeInterval:timeInterval dispatchQueue:dispatchQueue isOn:YES withBlock:block];
    }

  • (void)timerWithTimeInterval:(NSTimeInterval)timeInterval dispatchQueue:(dispatch_queue_t)dispatchQueue isOn:(BOOL)isOn withBlock:(void (^)(XHR_dispatch_timer *))block
    {
    XHR_dispatch_timer *timer = [[XHR_dispatch_timer alloc]initWithTimeInterval:timeInterval dispatchQueue:dispatchQueue withBlock:block];

    [self.timerDictionary setObject:timer forKey:[NSString stringWithFormat:@"timerIndex_%ld",timerIndex++]];
    //根據(jù)設(shè)置是否需要在初始化完成后開啟
    if (isOn) {
    timer.timerStatus = XHR_dispatch_timerStatusRuning;
    }
    }

- 那么解釋一下這里的XHR_dispatch_timer,它是定義在XHRTimer這個(gè)單例內(nèi)的一個(gè)私有類,是用來管理每一個(gè)timer對(duì)象的,以便在創(chuàng)建不同的timer對(duì)象執(zhí)行不同的任務(wù),并且定義了一個(gè)定時(shí)器狀態(tài)枚舉來標(biāo)記運(yùn)作狀態(tài),通過調(diào)整運(yùn)作狀態(tài)就可以控制定時(shí)器的開啟、暫停、取消等操作,也避免了多次開啟、暫停、取消而引起的bug,具體實(shí)現(xiàn)如下

  • (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval dispatchQueue:(dispatch_queue_t)dispatchQueue withBlock:(void(^)(XHR_dispatch_timer *))block
    {
    if (self = [super init]) {
    //timer本質(zhì)也是對(duì)象必須有強(qiáng)應(yīng)用引用,不然就會(huì)被釋放
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatchQueue);
    //設(shè)置開始時(shí)間和時(shí)間間隔
    dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, timeInterval * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    //設(shè)置回調(diào)時(shí)間
    dispatch_source_set_event_handler(self.timer, ^{
    block(self);
    });
    self.timerStatus = XHR_dispatch_timerStatusSuspend;
    }
    return self;
    }
  • (void)setTimerStatus:(XHR_dispatch_timerStatus)timerStatus
    {
    if (!self.timer) return;
    if (timerStatus == XHR_dispatch_timerStatusSuspend && _timerStatus != XHR_dispatch_timerStatusSuspend) {
    dispatch_suspend(self.timer);
    }
    else if (timerStatus == XHR_dispatch_timerStatusRuning && _timerStatus == XHR_dispatch_timerStatusSuspend)
    {
    dispatch_resume(self.timer);
    }
    else if(timerStatus == XHR_dispatch_timerStatusCanceled && _timerStatus != XHR_dispatch_timerStatusCanceled)
    {
    dispatch_cancel(self.timer);
    self.timer = nil;
    }
    _timerStatus = timerStatus;
    }

- 暫停定時(shí)器的方法


//暫停定時(shí)器

  • (void)suspend:(XHR_dispatch_timer *)timer
    {
    if (timer) {
    timer.timerStatus = XHR_dispatch_timerStatusSuspend;
    }
    }
  • (void)suspendAllTimer
    {
    [self.timerDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, XHR_dispatch_timer *_Nonnull obj, BOOL * _Nonnull stop) {
    obj.timerStatus = XHR_dispatch_timerStatusSuspend;
    }];
    }

- 手動(dòng)開啟/繼續(xù) 定時(shí)器的方法

//手動(dòng)開啟/繼續(xù) 定時(shí)器

  • (void)resume:(XHR_dispatch_timer *)timer
    {
    if (timer) {
    timer.timerStatus = XHR_dispatch_timerStatusRuning;
    }
    }
  • (void)resumeAllTimer
    {
    [self.timerDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, XHR_dispatch_timer *_Nonnull obj, BOOL * _Nonnull stop) {
    obj.timerStatus = XHR_dispatch_timerStatusRuning;
    }];
    }
- 取消定時(shí)器

//取消定時(shí)器
//取消定時(shí)器

  • (void)cancel:(XHR_dispatch_timer *)timer
    {
    if (timer) {
    timer.timerStatus = XHR_dispatch_timerStatusCanceled;
    }
    [self.timerDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
    if ([obj isEqual:timer]) {
    [self.timerDictionary removeObjectForKey:key];
    return;
    }
    }];
    }
  • (void)cancelAllTimer
    {
    [self.timerDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, XHR_dispatch_timer *_Nonnull obj, BOOL * _Nonnull stop) {
    obj.timerStatus = XHR_dispatch_timerStatusCanceled;
    }];
    [self.timerDictionary removeAllObjects];
    }
注:
- 調(diào)用方法和NSTimer類似,使用類方法,需要執(zhí)行的代碼直接寫在方法的block中,非常方便.需要注意的是,如果取消了定時(shí)器,如果想重新開啟就需要重新初始化,不然就會(huì)崩潰。
- bolock傳出去的參數(shù)是為了供外部解決循環(huán)應(yīng)用問題的

作者:胥鴻儒
demo地址:https://github.com/xuhongru/GCDTimer
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容