iOS - GCD 實現(xiàn)定時器、倒計時

標簽(空格分隔): 計時器 GCD timer 倒計時


GCD 定時器

NSTimer 的定時器是在 RunLoop 中實現(xiàn)的,由于RunLoop在處理各種任務(wù),所以會造成計時器不夠準確,有時候會相對慢一些,有沒有什么方法會讓計時變得準確?有,使用 GCD 的計時器方法會讓計時器變得相對準確,而且GCD不受RunLoop的 Mode 影響。

GCD 延時

我們之前寫過延時執(zhí)行的方法,其中 GCD 有一個延時執(zhí)行的方法,,只執(zhí)行一次,執(zhí)行完后,就不再執(zhí)行.如下代碼在這里等待兩秒鐘后執(zhí)行,執(zhí)行之后就結(jié)束了,不能起到定時器的作用.

//延時執(zhí)行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    
    NSLog(@"-------延時執(zhí)行--------");
});

GCD 定時器的實現(xiàn)

GCD 計時器,蘋果已經(jīng)有代碼提示啦!
GCD 計時器,蘋果已經(jīng)有代碼提示啦!

在之前寫一個GCD的定時器很麻煩,需要一步步創(chuàng)建,現(xiàn)在XCode中已經(jīng)有Timer的創(chuàng)建提示,選擇箭頭所指的方法,直接能過創(chuàng)建。

如下:

  dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, <#dispatchQueue#>);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, <#intervalInSeconds#> * NSEC_PER_SEC, <#leewayInSeconds#> * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
    <#code to be executed when timer fires#>
});
dispatch_resume(timer);

我們需要做的是,選擇其隊列類型,這里我選擇的是全局隊列。

創(chuàng)建 計時器 (參數(shù)注解)

/**
 *   GCD 計時器應(yīng)用
 *   dispatch Queue :決定了將來回調(diào)的方法在哪里執(zhí)行。
 *   dispatch_source_t timer  是一個OC對象
 *   DISPATCH_TIME_NOW  第二個參數(shù):定時器開始時間,也可以使用如下的方法,在Now 的時間基礎(chǔ)上再延時多長時間執(zhí)行以下任務(wù)。

 dispatch_time(<#dispatch_time_t when#>, <#int64_t delta#>)
 
 *   intervalInSeconds  第三個參數(shù):定時器開始后的間隔時間(納秒 NSEC_PER_SEC)
 *  leewayInSeconds 第四個參數(shù):間隔精準度,0代標最精準,傳入一個大于0的數(shù),代表多少秒的范圍是可以接收的,主要為了提高程序性能,積攢一定的時間,Runloop執(zhí)行完任務(wù)會睡覺,這個方法讓他多睡一會,積攢時間,任務(wù)也就相應(yīng)多了一點,而后一起執(zhí)行
 */

 // 全局隊列
dispatch_queue_t  queue = dispatch_get_global_queue(0, 0);

// 創(chuàng)建一個 timer 類型定時器 ( DISPATCH_SOURCE_TYPE_TIMER)
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

//設(shè)置定時器的各種屬性(何時開始,間隔多久執(zhí)行)
// GCD 的時間參數(shù)一般為納秒 (1 秒 = 10 的 9 次方 納秒)
// 指定定時器開始的時間和間隔的時間
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC, 0);

// 任務(wù)回調(diào)
dispatch_source_set_event_handler(timer, ^{
    NSLog(@"-----定時器-------");
});

// 開始定時器任務(wù)(定時器默認開始是暫停的,需要復位開啟)
dispatch_resume(timer);

GCD實現(xiàn)驗證碼倒計時

計時器
計時器
// 開啟倒計時效果

- (IBAction)openCountdown:(id)sender {
    

    __block NSInteger time = 59; //倒計時時間
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    dispatch_source_set_timer(timer,DISPATCH_TIME_NOW,1.0*NSEC_PER_SEC, 0); //每秒執(zhí)行
    
    dispatch_source_set_event_handler(timer, ^{
        
        if(time <= 0){ //倒計時結(jié)束,關(guān)閉
            
            dispatch_source_cancel(timer);
            
            dispatch_async(dispatch_get_main_queue(), ^{
                
                //設(shè)置按鈕的樣式
                [self.openSeconds setTitle:@"重新發(fā)送" forState:UIControlStateNormal];
                self.timeLabel.text = @"開始";

                self.openSeconds.userInteractionEnabled = YES;
            });
            
        }else{

            int seconds = time % 60;
            dispatch_async(dispatch_get_main_queue(), ^{
                
                
                //設(shè)置label讀秒效果
                self.timeLabel.text = [NSString stringWithFormat:@"重新發(fā)送(%.2d)",seconds];
                
                [self.openSeconds setTitle:@"已發(fā)送" forState:UIControlStateNormal];
                // 在這個狀態(tài)下 用戶交互關(guān)閉,防止再次點擊 button 再次計時
                self.openSeconds.userInteractionEnabled = NO;

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

相關(guān)閱讀更多精彩內(nèi)容

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