GCD定時器

大家平時開發(fā)中使用最多的定時器應該是NSTimer了,但是,NSTimer同時也存在一些弊端:比如,有時候你要把它添加到不同的runloop model上才能保證它正常執(zhí)行,又或者使用不當導致?lián)碛兴膶ο鬅o法釋放,又或者NSTimer本身的機制導致它并不是很精確。

下面就介紹一下GCD定時器的實現(xiàn):
GCD定時器其實是一種特殊的分派源,它是基于分派隊列的,而NSTimer是基于運行循環(huán)的,所以,尤其是在多線程中,GCD定時器要比NSTimer好用的多。另外,GCD定時器使用dispatch_block_t,而不是方法選擇器。

@interface GCDTimer : NSObject
+(GCDTimer *)repeatingTimerWithTimeInterval:(NSTimeInterval)seconds block:(dispatch_block_t)block;
@end
@interface GCDTimer()
@property (nonatomic, strong) dispatch_block_t block;
@property (nonatomic, strong) dispatch_source_t source;
@end

@implementation GCDTimer
+(GCDTimer *)repeatingTimerWithTimeInterval:(NSTimeInterval)seconds block:(dispatch_block_t)block {
    GCDTimer *timer = [[self alloc] init];
    timer.block = block;
    timer.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); // 首先,創(chuàng)建一個定時器分派源并綁定到主分派隊列上,這使得定時器總是在主線程上觸發(fā)
    uint64_t nsec = (uint64_t)(seconds * NSEC_PER_SEC);
    dispatch_source_set_timer(timer.source, dispatch_time(DISPATCH_TIME_NOW, nsec), nsec, 0);//設置定時器
    dispatch_source_set_event_handler(timer.source, block);//設置事件處理程序
    dispatch_resume(timer.source);//打開定時器(分派源通常都是需要配置的,所以它們創(chuàng)建的時候處于暫停狀態(tài),只有resume之后才會開始發(fā)送事件)
    return timer;
}

-(void)invalidate {
    if (self.source) {
        dispatch_source_cancel(self.source);
        self.source = nil;
    }
    self.block = nil;
}

-(void)dealloc {
    [self invalidate];//銷毀時將定時器設置為無效
}
@end

GCD定時器在各種runloop model下都是可以執(zhí)行的,因為它并不依賴與此,而NStimer,比如UIScrollView滾動的時候就需要添加到特定的model上才能執(zhí)行。

如果要后臺執(zhí)行定時器,只要添加一下設置即可:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    UIApplication*   app = [UIApplication sharedApplication];
    __block  UIBackgroundTaskIdentifier bgTask;
    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (bgTask != UIBackgroundTaskInvalid) {
                bgTask = UIBackgroundTaskInvalid;
            }
        });
    }];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            if (bgTask != UIBackgroundTaskInvalid) {
                bgTask = UIBackgroundTaskInvalid;
            }
        });
    });
}

<br /><br />
<br /><br /><br />



下面是swift 3.0的寫法:

class GCDTimer {
    var block: () -> Void
    var source: DispatchSourceTimer
    
    init(block: @escaping ()->Void, source: DispatchSourceTimer) {
        self.block = block
        self.source = source
    }

    
    class func repeatingTimer(timeInterval seconds: Double, block: @escaping () -> Void) -> GCDTimer {
        let source = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.main)
        let timer = GCDTimer(block: block, source: source)
        timer.source.scheduleRepeating(deadline: DispatchTime.now(), interval: seconds)
        timer.source.setEventHandler(handler: block)
        timer.source.resume()
        return timer
    }
    
    deinit {
        self.source.cancel()
    }
}

后臺執(zhí)行:

    func applicationDidEnterBackground(_ application: UIApplication) {
        
        let app = UIApplication.shared
        var bgTask: UIBackgroundTaskIdentifier!
        bgTask = app.beginBackgroundTask(expirationHandler: { 
            DispatchQueue.main.async {
                if bgTask != UIBackgroundTaskInvalid {
                    bgTask = UIBackgroundTaskInvalid
                }
            }
        })

        DispatchQueue.global().async {
            DispatchQueue.main.async {
                if bgTask != UIBackgroundTaskInvalid {
                    bgTask = UIBackgroundTaskInvalid
                }
            }
        }
    }

祝大家玩的愉快!

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

相關閱讀更多精彩內容

  • 相信大家在開發(fā)中都會使用到定時器, 但又常常對定時器的循環(huán)引用問題, NSTimer 釋放時機的選擇上,勞神費力!...
    GerryZhu閱讀 1,940評論 0 4
  • 提到定時器,NStimer肯定是我們最為熟悉的。 但是NStimer有著很大的缺點,并不準確。 通俗點說,就是它該...
    mengyingguo閱讀 404評論 0 0
  • 最近看了一下 iOS 的定時器的使用,我們來模擬一個發(fā)送短信驗證碼時候的等待計時動畫 要想了解定時器,首先需要了解...
    TomatosX閱讀 1,191評論 0 0
  • 定時器的實現(xiàn): GCD定時器優(yōu)缺點: 1.它不需要顯示的停掉定時器,由系統(tǒng)幫助我們處理。不需要考慮內存泄露問題。 ...
    frankisbaby閱讀 172評論 0 0
  • 2016~完成人生幾件大事~圓滿 全自助的一天慶祝我們的一周年~ 感恩遇見,希望接下來的日子用我們喜歡的方式攜手走...
    敏捷的魚兒閱讀 197評論 0 1

友情鏈接更多精彩內容