iOS中的定时器(GCD定时器)

3,094 阅读2分钟

「这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

关于GCD定时器

GCD定时器实际上是使用了 dispatch 源(dispatch source),dispatch 源监听系统内核对象并处理。dispatch 类似生产者消费者模式,通过监听系统内核对象,在生产者生产数据后自动通知相应的 dispatch 队列执行,后者充当消费者。通过系统级调用,更加精准


GCD定时器常用方法

  • 需要将dispatch_source_t timer设置为成员变量,不然会立即释放

    @property (nonatomic, strong) dispatch_source_t timer;
    
  • 创建定时器对象

    //创建线程队列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    //使用之前创建的队列来创建计时器
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    

    参数1:DISPATCH_SOURCE_TYPE_TIMER 为定时器类型
    参数2、3:中间两个参数对定时器无用
    参数4:在什么队列中使用

  • 设置定时器

    dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
    

    参数1:任务定时器
    参数2:任务开始时间
    参数3:任务间隔(单位均为纳秒)
    参数4:可接受的误差时间,设置0即不允许出现误差

  • 设置定时器任务

    dispatch_source_set_event_handler(self.timer, ^{
    
    });
    
  • 启动定时器,GCD计时器创建后需要手动启动

    dispatch_resume(self.timer);
    
  • 暂停定时器,暂停的时候注意,多次暂停的操作会导致线程锁的现象,即多少次暂停,对应多少次的继续操作,即 dispatch_suspenddispatch_resume 是成对出现的,计时器才会继续工作

    dispatch_suspend(self.timer);
    
  • 停止定时器

    dispatch_source_cancel(self.timer);
    

优点:

  • GCD定时器不依赖 runloop,他是一个独立的体系
  • 精度高,最小到1纳秒
  • 没有 invalidate 方法
  • 不需要手动管理内存(这里封装的target方式一定要注意循环引用)

GCD定时器的使用

示例:

@interface ViewController ()
@property (nonatomic, strong) dispatch_source_t timer;
@end

- (void)viewDidLoad {
    [super viewDidLoad];
    
    dispatch_queue_t queue = dispatch_get_main_queue();
    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
    
    dispatch_source_set_event_handler(self.timer, ^{
        NSLog(@"定时任务");
    });
    dispatch_resume(self.timer);
}

log:

Snip20211120_4.png