iOS GCD定時器

GCD定時器的優勢是不受RunLoop的運行模式的影響,它的的間隔時間是納秒為單位。

GCDTimer.h

#import <Foundation/Foundation.h>

typedef void (^TimerRunBlock)(NSUInteger currentTime);  //定時器計時回調
typedef void (^TimerStopBlock)();                       //定時器結束計時回調

@interface DPGCDTimer : NSObject

@property (nonatomic,assign)BOOL isTimerRuning;         //定時器是否正在運行
@property (nonatomic, copy) TimerStopBlock timerStopBlock;

/**
 *  定時器初始化(定時器默認開啟)
 *
 *  @param timeDuration  時長
 *  @param timerRunBlock 定時器回調
 */
- (void)timerWithTimeDuration:(double)timeDuration withRunBlock:(TimerRunBlock)timerRunBlock;


/**
 *  定時器停止
 */
- (void)stopTimer;

/**
 *  定時器恢復
 */
- (void)resumeTimer;

/**
 *  定時器暫停
 */
- (void)suspendTimer;

@end
#import "DPGCDTimer.h"
#define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;

@interface DPGCDTimer ()
{
    dispatch_source_t __block timer;
}

@property (nonatomic,copy)TimerRunBlock timerRunBlock;

@end

@implementation DPGCDTimer

- (void)timerWithTimeDuration:(double)timeDuration withRunBlock:(TimerRunBlock)timerRunBlock
{
    if (!timer) {
        WS(weakSelf);
        //創建定時器
        _isTimerRuning = YES;
        NSUInteger __block time = timeDuration;
        
        self.timerRunBlock = timerRunBlock;
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
        dispatch_source_set_timer(timer,dispatch_walltime(NULL, 0),1 * NSEC_PER_SEC, 0); //每秒執行
        dispatch_source_set_event_handler(timer, ^{
            if (time <= 0) {
                [self stopTimer];
            } else {
                if (weakSelf.timerRunBlock) {
                    weakSelf.timerRunBlock(time --);
                }
            }
        });
        dispatch_resume(timer);
    }
    
}

//停止
- (void)stopTimer
{
    if(timer){
        if (_isTimerRuning) {
            dispatch_source_cancel(timer);
            timer = nil;
            _isTimerRuning = NO;
            if (self.timerStopBlock) {
                self.timerStopBlock();
            }
        }
        
    }
}

//恢復
- (void)resumeTimer
{
    if(timer){
        if (!_isTimerRuning) {
            dispatch_resume(timer);
            _isTimerRuning = YES;
        }
        
    }
}

//暫停
- (void)suspendTimer
{
    if(timer){
        if (_isTimerRuning) {
            dispatch_suspend(timer);
            _isTimerRuning = NO;
        }
    }
}


@end

PS:
GCD 中刷新UI導致線程崩潰問題工具 - PSPDFUIKitMainThreadGuard
工具使用方法就是把這個.m文件拖入工程,如果有問題就會PSPDFAssert斷點處停住。在左側線程分析中點擊查看出現錯誤的地方。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 最近看了一下 iOS 的定時器的使用,我們來模擬一個發送短信驗證碼時候的等待計時動畫 要想了解定時器,首先需要了解...
    TomatosX閱讀 1,158評論 0 0
  • 前言 最近離職了,可以盡情熬夜寫點總結,不用擔心第二天上班爽并蛋疼著,這篇的主角 RunLoop 一座大山,涵蓋的...
    zerocc2014閱讀 12,434評論 13 67
  • 本文首發于我的個人博客:「程序員充電站」[https://itcharge.cn]文章鏈接:「傳送門」[https...
    ITCharge閱讀 60,744評論 50 540
  • 1,NSObject中description屬性的意義,它可以重寫嗎?答案:每當 NSLog(@"")函數中出現 ...
    eightzg閱讀 4,190評論 2 19
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,210評論 30 471