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
断点处停住。在左侧线程分析中点击查看出现错误的地方。