在iOS开发的过程中定时器的使用比较频繁的,比较常见的场景是验证码的发送,或者是倒计时的展示.一般的需求我们直接使用NSTimer就能完成。但是NSTimer的坑也是比较多的,比如在UITableview的时候,需要把NSTimer添加到主循环,并且设置为NSRunLoopCommonModes。但是今天要记录的是:GCD定时器
先直接贴代码
File:GCDCountDown.h
@interface GCDCountDown()
@property(nonatomic,strong)dispatch_source_t timer;
+(instancetype)manager;
-(void)resume;
-(void)pause;
@end
*************************************************************************************
File:GCDCountDown.m
@implementation GCDCountDown
+(instancetype)manager{
static GCDCountDown *countDown = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (countDown == nil) {
countDown = [[GCDCountDown alloc]init];
}
});
return countDown;
}
-(instancetype)init{
self = [super init];
if (self) {
[self loadTimer];
}
return self;
}
//定时器设置
-(void)loadTimer{
if (self.timer) {
dispatch_cancel(self.timer);
self.timer = nil;
}
dispatch_queue_t queue = dispatch_get_main_queue();
//创建一个定时器(dispatch_source_t本质上还是一个OC对象)
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//设置定时器的各种属性
dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0*NSEC_PER_SEC));
uint64_t interval = (uint64_t)(1.0*NSEC_PER_SEC);
dispatch_source_set_timer(self.timer, start, interval, 0);
//设置回调
__weak typeof(self) weakSelf = self;
dispatch_source_set_event_handler(self.timer, ^{
//定时器需要执行的操作
[weakSelf timerAction];
});
//启动定时器(默认是暂停)
dispatch_resume(self.timer);
}
-(void)resume{
//重新加载一次定时器
[self loadTimer];
}
-(void)pause{
if (self.timer) {
dispatch_cancel(self.timer);
self.timer = nil;
}
}
@end
这是为了适配项目的需求封装的一个简单的定时器单例,精简了一些业务代理,不过主要的用法都贴出来了。GCD定时器的定义和使用就是这么简单,但是其中有几点是需要说明的:
- dispatch_source_t 在本质上是一个对象,所以我们使用强引用。我们可以点击dispatch_source_t跳转到source.h文件看到,改对象使用宏定义,进行了一系列操作定义对象。
dispatch_source_t展开后的定义是:
@protocol OS_dispatch_source <OS_dispatch_object>
@end
typedef NSObject<OS_dispatch_source>* dispatch_source_t
也就是dispatch_source_t 就是一个NSObjective对象。对于想深入了解的同学自行百度(主要是本人实在没有那么多精力看源码)
- 定时器的暂停使用的是:dispatch_cancel(self.timer) 很明显这个我们可以清楚得看到也是一个宏定义,至于他的内部操作,请参考上一句话
- 相对于NSTimer来说GCD定时器更加精确,并且不用考虑运行模式,因为NSTimer其实是延迟把事件放到RunLoop中执行,如果遇到其他的事件导致NSTimer的事件执行错过了运行周期,就会导致NSTimer的事件要到下一个周期才能运行。
网友评论