有三种方案
001 NSTimer 需要依赖于指定runloop的运行模式
002 NSObject.performSelector:withObject:afterDelay: 依赖runloop
003 dispatch_after 不依赖Runloop
- (void)testDispatchAfter{
NSLog(@"start----%s----",__func__);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"3秒----");
});
}
2020-10-29 20:56:59.818162+0800 GCDPropertyQueue[1828:86866] start-----[ViewController testDispatchAfter]----
2020-10-29 20:57:02.818514+0800 GCDPropertyQueue[1828:86866] 3秒----
还是看源码
static inline void
_dispatch_after(dispatch_time_t when, dispatch_queue_t dq,
void *ctxt, void *handler, bool block)
{
dispatch_timer_source_refs_t dt;
dispatch_source_t ds;
uint64_t leeway, delta;
if (when == DISPATCH_TIME_FOREVER) {
#if DISPATCH_DEBUG
DISPATCH_CLIENT_CRASH(0, "dispatch_after called with 'when' == infinity");
#endif
return;
}
//获取到时间
delta = _dispatch_timeout(when);
if (delta == 0) { //如果为零那么开启异步线程立马执行
if (block) {
return dispatch_async(dq, handler);
}
return dispatch_async_f(dq, ctxt, handler);
}
leeway = delta / 10; // <rdar://problem/13447496>
//NSEC_PER_MSEC 一毫秒
if (leeway < NSEC_PER_MSEC) leeway = NSEC_PER_MSEC;
if (leeway > 60 * NSEC_PER_SEC) leeway = 60 * NSEC_PER_SEC;
// this function can and should be optimized to not use a dispatch source
//创建一个调度资源
ds = dispatch_source_create(&_dispatch_source_type_after, 0, 0, dq);
dt = ds->ds_timer_refs;
//分配一个持续调度对象
dispatch_continuation_t dc = _dispatch_continuation_alloc();
if (block) {
_dispatch_continuation_init(dc, dq, handler, 0, 0);
} else {
_dispatch_continuation_init_f(dc, dq, ctxt, handler, 0, 0);
}
// reference `ds` so that it doesn't show up as a leak
dc->dc_data = ds;
_dispatch_trace_item_push(dq, dc);
os_atomic_store2o(dt, ds_handler[DS_EVENT_HANDLER], dc, relaxed);
dispatch_clock_t clock;
uint64_t target;
//调度时间给时钟以及target
_dispatch_time_to_clock_and_value(when, &clock, &target);
//判断是否是调度时针墙
if (clock != DISPATCH_CLOCK_WALL) {
//调整精度
leeway = _dispatch_time_nano2mach(leeway);
}
//du_timer_flags 异或从clock异步时间
// 执行target
//执行时间间隔以及截止时间
//保持活跃度
dt->du_timer_flags |= _dispatch_timer_flags_from_clock(clock);
dt->dt_timer.target = target;
dt->dt_timer.interval = UINT64_MAX;
dt->dt_timer.deadline = target + leeway;
dispatch_activate(ds);
}
void
dispatch_after(dispatch_time_t when, dispatch_queue_t queue,
dispatch_block_t work)
{
_dispatch_after(when, queue, NULL, work, true);
}
dispatch_after 并不是在指定时间后执行,而是在指定时间之后才将任务提交到队列中
_dispatch_trace_item_push(dq, dc);
os_atomic_store2o(dt, ds_handler[DS_EVENT_HANDLER], dc, relaxed);
dispatch_after在延后执行的block中无法直接取消
dt->du_timer_flags |= _dispatch_timer_flags_from_clock(clock);
dt->dt_timer.target = target;
dt->dt_timer.interval = UINT64_MAX;
dt->dt_timer.deadline = target + leeway;
dispatch_activate(ds);
判断when是否是现在,异步执行它,否则创建一个dispatch source 以便在指定时间触发异步执行