dispatch source 总结

项目里用到定时器时,看同事是这么写的:

@property (nonatomic,strong) dispatch_source_t timer;

if (!self.timer) {
        dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
        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 * NSEC_PER_SEC);
        dispatch_source_set_timer(self.timer, start, interval, 0);
        dispatch_source_set_event_handler(self.timer, ^{
            //            NSLog(@"定时器开启中........");
            dispatch_async(dispatch_get_main_queue(), ^{
            //            主线程添加事件处理
            });
        });
        
        //启动定时器
        dispatch_resume(self.timer);
    }

/**
 * 移除定时器
 */
- (void)removeTimer {
    if (self.timer) {
        dispatch_source_cancel(self.timer);
        self.timer = nil;
    }
}

跟自己写的NSTimer档次不一样,感觉这个逼格好高啊,然后就研究了下 dispatch_sourcer在定时器里的使用,如下。

定时器dispatch source定时产生事件,可以用来发起定时执行的任务,所有定时器dispatch source都是间隔定时器,一旦创建,会按你指定的间隔定期递送事件。你需要为定时器dispatch source指定一个期望的定时器事件精度,也就是leeway值,让系统能够灵活地管理电源并唤醒内核。例如系统可以使用leeway值来提前或延迟触发定时器,使其更好地与其它系统事件结合。创建自己的定时器时,你应该尽量指定一个leeway值。

就算你指定leeway值为0,也不要期望定时器能够按照精确的纳秒来触发事件。系统会尽可能地满足你的需求,但是无法保证完全精确的触发时间。

当计算机睡眠时,定时器dispatch source会被挂起,稍后系统唤醒时,定时器dispatch source也会自动唤醒。根据你提供的配置,暂停定时器可能会影响定时器下一次的触发。如果定时器dispatch source使用 dispatch_time 函数或DISPATCH_TIME_NOW 常量设置,定时器dispatch source会使用系统默认时钟来确定何时触发,但是默认时钟在计算机睡眠时不会继续。

如果你使用dispatch_walltime函数来设置定时器dispatch source,则定时器会根据挂钟时间来跟踪,这种定时器比较适合触发间隔相对比较大的场合,可以防止定时器触发间隔出现太大的误差。

下面是定时器dispatch source的一个例子,每30秒触发一次,leeway值为1,因为间隔相对较大,使用 dispatch_walltime 来创建定时器。定时器会立即触发第一次,随后每30秒触发一次。MyPeriodicTask 和 MyStoreTimer 是自定义函数,用于实现定时器的行为,并存储定时器到应用的数据结构。

dispatch_source_t CreateDispatchTimer(uint64_t interval, 
uint64_t leeway, 
dispatch_queue_t queue, 
dispatch_block_t block) 
{ 
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 
0, 0, queue); 
if (timer) 
{ 
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway); 
dispatch_source_set_event_handler(timer, block); 
dispatch_resume(timer); 
} 
return timer; 
}

void MyCreateTimer() 
{ 
dispatch_source_t aTimer = CreateDispatchTimer(30ull * NSEC_PER_SEC, 
1ull * NSEC_PER_SEC, 
dispatch_get_main_queue(), 
^{ MyPeriodicTask(); });

// Store it somewhere for later use. 
if (aTimer) 
{ 
MyStoreTimer(aTimer); 
} 
}

虽然定时器dispatch source是接收时间事件的主要方法,你还可以使用其它选择。如果想在指定时间间隔后执行一个block,可以使用 dispatch_after 或 dispatch_after_f函数。这两个函数非常类似于dispatch_async,但是只允许你指定一个时间值,时间一到就自动提交block到queue中执行,时间值可以指定为相对或绝对时间。

支持原创

然后我总结了下用dispatch_source写定时器的优缺点
优点:
1、可以暂停,继续。 不用像NSTimer一样需要重新创建。
2、性能较好。
缺点:
1、每次resume都会先执行一次。
共同点:
1、如果不手动释放就不会走dealloc。
2、不精确

你可能感兴趣的:(dispatch source 总结)