日常开发中对GCD
用的最多的便是async和sync
,也便是异步去做和同步去做
某个使命,但是关于GCD来说可不止单单这个功用,本文首要看下GCD的其他功用如栅门函数、信号量、调度组以及dispatch_once
等等。
dispatch_once初始化游戏启动器失败
咱们在日常开时间复杂度发中会常常运用单例,而单例的写法也并初始化电脑的后果不陌生,如下所示:
+(instancetype) shareManager{
static dispatch_once_t once;
static FMUserManager *shareManager;
dispatch_once(&once,^{
shareManager = [[FMUserManager alloc]init];
});
return shareManager;
}
这傍边就运用了dispatch_once
函数,来确保block代码
只会履行一次,那么他又是怎源码精灵永久兑换码么初始化电脑时出现问题确保的呢?首要苹果手机怎么录屏就来看下源码:
void
dispatch_once(dispatch_once_t *val, dispatch_block_t block)
{
dispatch_once_f(val, block, _dispatch_Block_invoke(block));
}
void
dispatch_once_f(dispatch_once_t *val, void *ctxt, dispatch_function_t func)
{
dispatch_once_gate_t l = (dispatch_once_gate_t)val;
#if !DISPATCH_ONCE_INLINE_FASTPATH || DISPATCH_ONCE_USE_QUIESCENT_COUNTER
uintptr_t v = os_atomic_load(&l->dgo_once, acquire);
if (likely(v == DLOCK_ONCE_DONE)) {
return;
}
#if DISPATCH_ONCE_USE_QUIESCENT_COUNTER
if (likely(DISPATCH_ONCE_IS_GEN(v))) {
return _dispatch_once_mark_done_if_quiesced(l, v);
}
#endif
#endif
if (_dispatch_once_gate_tryenter(l)) {
return _dispatch_once_callout(l, ctxt, func);
}
return _dispatch_once_wait(l);
}
这儿首线程安全要对使命block
进行源码编程器了一下包装,然后调用disp初始化电脑时出现问题未进行更改atch算法复杂度_once_f
函数,在该函初始化电脑时出现问题未进行更改数中又有三种状况,也便是:
- 假如之前调用过
bl苹果xrock使命
,那么就直接回来; - 假如初始化之前没有调用过,就去履行使命,也便是调用
_dispatch_once_callout
; - 假如正在履行中,就死循环查询使命状况,直至使命状况改动,也便是调用
_disp源码中的图片atch_once_wait
函数;
首要来看下履行使命_dispatch_once_callout
static void
_dispatch_once_callout(dispatch_once_gate_t l, void *ctxt,
dispatch_function_t func)
{
_dispatch_client_callout(ctxt, func);
_dispatch_once_gate_broadcast(l);
}
static inline void
_dispatch_once_gate_broadcast(dispatch_once_gate_t l)
{
dispatch_lock value_self = _dispatch_lock_value_for_self();
uintptr_t v;
#if DISPATCH_ONCE_USE_QUIESCENT_COUNTER
v = _dispatch_once_mark_quiescing(l);
#else
v = _dispatch_once_mark_done(l);
#endif
if (likely((dispatch_lock)v == value_self)) return;
_dispatch_gate_broadcast_slow(&l->dgo_gate, (dispatch_lock)v);
}
static inline uintptr_t
_dispatch_once_mark_done(dispatch_once_gate_t dgo)
{
return os_atomic_xchg(&dgo->dgo_once, DLOCK_ONCE_DONE, release);
}
#define os_atomic_xchg(p, v, m)
atomic_exchange_explicit(_os_atomic_c11_atomic(p), v, memory_order_##m)
调用_dispatch_once_callout
函数后,首要履行_dispatch_client_callout
去苹果手机怎么录屏调用block使命
(在单例中也便是去初始化实例目标),然后调用_dispatch_once_gate_broadcast
进行调用后的符号处理,os_atomic_xchg
函数便是将传进来的di苹果13spatch_o源码网站nce
参数与DLOCK_ON线程数是什么CE_DONE
做交流,以表明履行过该block使命
当第2次调用dispa初始化失败是怎么解决tch_o苹果手机怎么录屏nc环复杂度e_f
的时分,会首要进行os_atomic_load(&am苹果范冰冰p;l->dgo_onc线程池e, acq源码uire)
的取值判别:
#define os_atomic_load(p, m)
atomic_load_explicit(_os_atomic_c11_atomic(p), memory_order_##m)
由此,结合上方os_atomic_xchg
宏函数,可知这儿会将DLOCK_ONCE_DONE
的值取出来,进行if (v == DLOCK_ONCE_DON苹果官网E)
判别,也便是说,之前只要履行过block使命
,那么第2次调用dispatch_once_源码1688f
就会直接回来。
那苹果x假如bl线程池的七个参数ock使命
正在履行时,调用了dispatch_once初始化sdk什么意思_f
函数呢,这时就会走_dispatch_once_wait
在这儿就会一向死循环读取dgo->源码时代;dgo_once
的状况,直至超时线程撕裂者或许跳出循环。
栅门函数
首要来看一个栅门函数的比如:
dispatch_queue_t t = dispatch_queue_create("fm", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(t, ^{
NSLog(@"1");
});
dispatch_async(t, ^{
NSLog(@"2");
});
// 栅门函数
dispatch_barrier_async(t, ^{
NSLog(@"3");
});
NSLog(@"4");
dispatch_async(t, ^{
NSLog(@"5");
});
栅门函数是GCD供给的用于阻塞分割使命的一组函数
。就像其界说相同,其首要作用便是在行列中设置栅门,来人为干预行列中使命的履行顺序.常用的栅门函数有两个dispatch_barrier_async
和dispatch_barrier_sync
,
由于同复杂度怎么计算的步函数是立即履行,剖析栅门函数的复杂度要比异步函数简略些,因此在这儿咱们首要看下dispatch_barrier_sync
。
当时串环路复杂度行行列源码网站时,咱们看下调用同步栅门函数的流程
void
dispatch_barrier_sync(dispatch_queue_t dq, dispatch_block_t work)
{
uintptr_t dc_flags = DC_FLAG_BARRIER | DC_FLAG_BLOCK;
if (unlikely(_dispatch_block_has_private_data(work))) {
return _dispatch_sync_block_with_privdata(dq, work, dc_flags);
}
_dispatch_barrier_sync_f(dq, work, _dispatch_Block_invoke(work), dc_flags);
}
static void
_dispatch_barrier_sync_f(dispatch_queue_t dq, void *ctxt,
dispatch_function_t func, uintptr_t dc_flags)
{
_dispatch_barrier_sync_f_inline(dq, ctxt, func, dc_flags);
}
static inline void
_dispatch_barrier_sync_f_inline(dispatch_queue_t dq, void *ctxt,
dispatch_function_t func, uintptr_t dc_flags)
{
...省掉部分代码...
if (unlikely(!_dispatch_queue_try_acquire_barrier_sync(dl, tid))) {
return _dispatch_sync_f_slow(dl, ctxt, func, DC_FLAG_BARRIER, dl,
DC_FLAG_BARRIER | dc_flags);
}
...省掉部分代码...
_dispatch_introspection_sync_begin(dl);
_dispatch_lane_barrier_sync_invoke_and_complete(dl, ctxt, func
DISPATCH_TRACE_ARG(_dispatch_trace_item_sync_push_pop(
dq, ctxt, func, dc_flags | DC_FLAG_BARRIER)));
}
static void
_dispatch_sync_f_slow(dispatch_queue_class_t top_dqu, void *ctxt,
dispatch_function_t func, uintptr_t top_dc_flags,
dispatch_queue_class_t dqu, uintptr_t dc_flags)
{
...省掉部分代码...
_dispatch_trace_item_push(top_dq, &dsc);
__DISPATCH_WAIT_FOR_QUEUE__(&dsc, dq);
if (dsc.dsc_func == NULL) {
// dsc_func being cleared means that the block ran on another thread ie.
// case (2) as listed in _dispatch_async_and_wait_f_slow.
dispatch_queue_t stop_dq = dsc.dc_other;
return _dispatch_sync_complete_recurse(top_dq, stop_dq, top_dc_flags);
}
_dispatch_introspection_sync_begin(top_dq);
_dispatch_trace_item_pop(top_dq, &dsc);
_dispatch_sync_invoke_and_complete_recurse(top_dq, ctxt, func,top_dc_flags
DISPATCH_TRACE_ARG(&dsc));
}
首要经过源码能够看到大体的调用流程dispatch_barrier_sync->_dispatch_bar初始化英文rier_源码sync_f->_disp时间复杂度atch_sync_f线程安全_slow
(这儿能够经过增加符号断点的方法进行验证),然后进入到_dispatch_sync_f_slow
函数,在_dispatch_sync_f_slow
函数中,__DISPATCH_WAIT_FOR_QUEUE__
函数会判别是否会发生死锁以及等候行列的履行(串行行列会等候上一使命履行完毕再履行下一使命),然后调用_dispatch_sync_invoke_and_complete_排序复杂度recurse
去同步履行栅门函数使命。
static void
_dispatch_sync_invoke_and_complete_recurse(dispatch_queue_class_t dq,
void *ctxt, dispatch_function_t func, uintptr_t dc_flags
DISPATCH_TRACE_ARG(void *dc))
{
_dispatch_sync_function_invoke_inline(dq, ctxt, func);
_dispatch_trace_item_complete(dc);
_dispatch_sync_complete_recurse(dq._dq, NULL, dc_flags);
}
static void
_dispatch_sync_complete_recurse(dispatch_queue_t dq, dispatch_queue_t stop_dq,
uintptr_t dc_flags)
{
bool barrier = (dc_flags & DC_FLAG_BARRIER);
do {
if (dq == stop_dq) return;
if (barrier) {
dx_wakeup(dq, 0, DISPATCH_WAKEUP_BARRIER_COMPLETE);
} else {
_dispatch_lane_non_barrier_complete(upcast(dq)._dl, 0);
}
dq = dq->do_targetq;
barrier = (dq->dq_width == 1);
} while (unlikely(dq->do_targetq));
}
_dispatch_sync_源码编辑器function_invoke_inline
函数里边会线程安全经过callout
去回调履行栅门函数的使命,履行完后调用_dispatch_sync_complete_recurse
去循环判别当时行列是否还有栅门函数,假如有,则调用dx_wakeup
宏函数,也便是_dispatch_lane_复杂度push
办法
DISPATCH_VTABLE_INSTANCE(workloop,
...省掉部分代码...
.dq_wakeup = _dispatch_workloop_wakeup,
.dq_push = _dispatch_workloop_push,
);
DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_serial, lane,
...省掉部分代码...
.dq_wakeup = _dispatch_lane_wakeup,
.dq_push = _dispatch_lane_push,
);
DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_concurrent, lane,
...省掉部分代码...
.dq_wakeup = _dispatch_lane_wakeup,
.dq_push = _dispatch_lane_concurrent_push,
);
DISPATCH_VTABLE_SUBCLASS_INSTANCE(queue_global, lane,
...省掉部分代码...
.dq_wakeup = _dispatch_root_queue_wakeup,
.dq_push = _dispatch_root_queue_push,
);
在这儿咱们看到不同行列,dq_wakeup
会调用不同的苹果手机怎么录屏函数:
- 当是大局并发行列的时分,调用
_dispatch_root_queue_push
,但提示Don't try to wake up or override a root queue不要试图唤醒或覆盖根行列
,原因也很简略,大局并发行列体系也在调用,假如被栅门函数栅住,会导致体系的代码履行也出问题;源码编程器总归:栅门函数是拦不住大局并发行列的
。 - 假如是自界说的并发行列或许串行行列,调用
_dispatch_lane_wakeup
void
_dispatch_lane_wakeup(dispatch_lane_class_t dqu, dispatch_qos_t qos,
dispatch_wakeup_flags_t flags)
{
dispatch_queue_wakeup_target_t target = DISPATCH_QUEUE_WAKEUP_NONE;
if (unlikely(flags & DISPATCH_WAKEUP_BARRIER_COMPLETE)) {
// 栅门函数使命完结后调用该函数
return _dispatch_lane_barrier_complete(dqu, qos, flags);
}
if (_dispatch_queue_class_probe(dqu)) {
target = DISPATCH_QUEUE_WAKEUP_TARGET;
}
// 唤醒后边行列中的使命,履行栅门函数后边行列里的使命
return _dispatch_queue_wakeup(dqu, qos, flags, target);
}
然后调用_d源码网站ispatch_lane_barrier_complete
函数。在该函数中,终究调用_dispatch_lane_class_barrier_complete
办法,完结栅门的铲除,从而回来到_dispat环形复杂度ch_lane源码_苹果xrwakeup
中线程池面试题履行栅门函数之后的使命。
总苹果12结:
栅门函数的作用:
等候栅门函数前增加到行列里边的使命悉数履行完结之后,才会履行栅门函数里边的使命,栅门函数里边的使命履行完结之后才会履行栅门函数后边的行列里边的使命。
需求留意的点:
- 栅门函数只对同一行列起作用。
- 栅门函数对大局并发行列无效。
另:那为什么栅门函数还区别同线程池的七个参数步和异步函数呢?
其实便是栅门函数本身的使命是否算法复杂度需求开辟线程去进行履行来区别运用同步仍是异步函数
总结:
- 栅门函数只对同⼀行列起作⽤。
- 栅门函数对大局并发行列⽆效。
调度组算法复杂度
上述的栅门函数源码编程器也说到,其只会对同一行列起作用,但在日常开发中遇到多行列的使命时,栅门函数就歇菜了,这时就用到了调度组dispatch_初始化是什么意思group
,咱们在日常开发中,常常看到如下代码:
-(void)test{
dispatch_group_t g = dispatch_group_create();
dispatch_queue_t que1 = dispatch_queue_create("lg1", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t que2 = dispatch_queue_create("lg2", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_enter(g);
dispatch_async(que1, ^{
sleep(2);
NSLog(@"1");
dispatch_group_leave(g);
});
dispatch_group_enter(g);
dispatch_async(que2, ^{
sleep(3);
NSLog(@"2");
dispatch_group_leave(g);
});
dispatch_group_enter(g);
dispatch_async(dispatch_get_global_queue(0, 0 ), ^{
sleep(4);
NSLog(@"3");
dispatch_group_leave(g);
});
dispatch_group_enter(g);
dispatch_async(dispatch_get_main_queue(), ^{
sleep(5);
NSLog(@"4");
dispatch_group_leave(g);
});
dispatch_group_notify(g, dispatch_get_global_queue(0, 0), ^{
NSLog(@"5");
});
}
这种以dispatch_group_enter
和dispatch_group_leave
调配运初始化sdk什么意思用的线程数是什么方法其实和下方这种是相同的。
dispatch_group_t g = dispatch_group_create();
dispatch_queue_t que1 = dispatch_queue_create("lg1", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t que2 = dispatch_queue_create("lg2", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(g, que1, ^{
NSLog(@"我是另一种调用方法");
});
咱们能够经过源码来证明一下空间复杂度:
void
dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_block_t db)
{
dispatch_continuation_t dc = _dispatch_continuation_alloc();
uintptr_t dc_flags = DC_FLAG_CONSUME | DC_FLAG_GROUP_ASYNC;
dispatch_qos_t qos;
qos = _dispatch_continuation_init(dc, dq, db, 0, dc_flags);
_dispatch_continuation_group_async(dg, dq, dc, qos);
}
static inline void
_dispatch_continuation_group_async(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_continuation_t dc, dispatch_qos_t qos)
{
dispatch_group_enter(dg);
dc->dc_data = dg;
_dispatch_continuation_async(dq, dc, qos, dc->dc_flags);
}
......
static inline void
_dispatch_continuation_with_group_invoke(dispatch_continuation_t dc)
{
struct dispatch_object_s *dou = dc->dc_data;
unsigned long type = dx_type(dou);
if (type == DISPATCH_GROUP_TYPE) {
_dispatch_client_callout(dc->dc_ctxt, dc->dc_func);
_dispatch_trace_item_complete(dc);
dispatch_group_leave((dispatch_group_t)dou);
} else {
DISPATCH_INTERNAL_CRASH(dx_type(dou), "Unexpected object type");
}
}
能够看到
-
dispatch_group_async
调用的_dispatch_continuation_group_async
函数线程撕裂者,一进入就调用了dispatch_group_enter(dg)
, - 而在异步函数运转到
_dispatch_continuation_invoke_inline->_dispatch_continuation_with_group_invoke
时,在履行完_dispatch_client_callout
也便是履行完block使命
之后,就调用dispatch_group_leave()
进行出组操作。
关于dispa时间复杂度tch_group_asyn排序复杂度c
在documentatio初始化失败是怎么解决n
文件中有如下界说,这种界说也会更好了解写。
void
dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block)
{
dispatch_retain(group);
dispatch_group_enter(group);
dispatch_async(queue, ^{
block();
dispatch_group_leave(group);
dispatch_release(group);
});
}
那dispatch_group_enter
和dispatch_group_leave
又做了什么操作呢?
void
dispatch_group_enter(dispatch_group_t dg)
{
// The value is decremented on a 32bits wide atomic so that the carry
// for the 0 -> -1 transition is not propagated to the upper 32bits.
uint32_t old_bits = os_atomic_sub_orig2o(dg, dg_bits,
DISPATCH_GROUP_VALUE_INTERVAL, acquire);
uint32_t old_value = old_bits & DISPATCH_GROUP_VALUE_MASK;
if (unlikely(old_value == 0)) {
_dispatch_retain(dg); // <rdar://problem/22318411>
}
if (unlikely(old_value == DISPATCH_GROUP_VALUE_MAX)) {
DISPATCH_CLIENT_CRASH(old_bits,
"Too many nested calls to dispatch_group_enter()");
}
}
首要在苹果的官方文档中关于dispatch_group_enter
有初始化英文这么一段话的解释:
Calling this function increments the curren初始化电脑t count of outstanding tasks in the group. 调用此函数会增加组中当时未完结使命的计数。
- 经线程数是什么过源码及注初始化电脑的后果释可知
os_atomic_sub_orig2o
函数会进行减
操作,也便是说增加了组中的未完初始化磁盘结使命数。 - 这儿的两个参苹果12数
dg, dg_bits
会经过os_atomic_sub_orig2o
宏函数变成这个姿态os_atomic_sub_orig(&(dg)->dg_bits, (v), m)
也便是说其实是对dg_bits
进行初始化游戏启动器失败赋值。
void
dispatch_group_leave(dispatch_group_t dg)
{
// The value is incremented on a 64bits wide atomic so that the carry for
// the -1 -> 0 transition increments the generation atomically.
uint64_t new_state, old_state = os_atomic_add_orig2o(dg, dg_state,
DISPATCH_GROUP_VALUE_INTERVAL, release);
uint32_t old_value = (uint32_t)(old_state & DISPATCH_GROUP_VALUE_MASK);
if (unlikely(old_value == DISPATCH_GROUP_VALUE_1)) {
old_state += DISPATCH_GROUP_VALUE_INTERVAL;
do {
new_state = old_state;
if ((old_state & DISPATCH_GROUP_VALUE_MASK) == 0) {
new_state &= ~DISPATCH_GROUP_HAS_WAITERS;
new_state &= ~DISPATCH_GROUP_HAS_NOTIFS;
} else {
// If the group was entered again since the atomic_add above,
// we can't clear the waiters bit anymore as we don't know for
// which generation the waiters are for
new_state &= ~DISPATCH_GROUP_HAS_NOTIFS;
}
if (old_state == new_state) break;
} while (unlikely(!os_atomic_cmpxchgv2o(dg, dg_state,
old_state, new_state, &old_state, relaxed)));
return _dispatch_group_wake(dg, old_state, true);
}
if (unlikely(old_value == 0)) {
DISPATCH_CLIENT_CRASH((uintptr_t)old_value,
"Unbalanced call to dispatch_group_leave()");
}
}
-
dispatch_group_leave
函数其实便是对dg_state
进行加
操作,-dg_state
其实便是dispatch_group源码编程器_enter
函数中的dg_bits源码编辑器下载
,其本质是个联初始化电脑时出现问题未进行更改合体,共用同一段内存,界说如下:
DISPATCH_UNION_LE(uint64_t volatile dg_state,
uint32_t dg_bits,
uint32_t dg_gen
) DISPATCH_ATOMIC64_ALIGN
- 当
dg_state增加
的时分,也便是有一个出组操作,就去调用_dispatc苹果范冰冰h_gr复杂度怎么计算的oup_wake
去唤醒其他苹果手机使命。
static inline void
_dispatch_group_notify(dispatch_group_t dg, dispatch_queue_t dq,
dispatch_continuation_t dsn)
{
uint64_t old_state, new_state;
dispatch_continuation_t prev;
dsn->dc_data = dq;
_dispatch_retain(dq);
prev = os_mpsc_push_update_tail(os_mpsc(dg, dg_notify), dsn, do_next);
if (os_mpsc_push_was_empty(prev)) _dispatch_retain(dg);
os_mpsc_push_update_prev(os_mpsc(dg, dg_notify), prev, dsn, do_next);
if (os_mpsc_push_was_empty(prev)) {
os_atomic_rmw_loop2o(dg, dg_state, old_state, new_state, release, {
new_state = old_state | DISPATCH_GROUP_HAS_NOTIFS;
if ((uint32_t)old_state == 0) {
os_atomic_rmw_loop_give_up({
return _dispatch_group_wake(dg, new_state, false);
});
}
});
}
}
而在dispatch_group_notify
中苹果手机怎么录屏这儿咱们就看到:dispatch_group_n初始化英文otify
中会判别old_state == 0
来判别enter和leave
是否都已履行。
信号源码交易平台量
在G初始化CD中还初始化有一种操控使命履行顺序的方法,也便是信号量,不过它操控的其实是并发数量。咱们一般运用如下三个函数:
-
dispatch_初始化电脑的后果semaphore_create(复杂度long value)
这个函数是创立一个dispatch_semaphor苹果因不送充电器被判赔7000元e_t
类型的信号苹果因不送充电器被判赔7000元量,而且创立的时分需求指定信号量的巨细。 -
dis初始化磁盘patc复杂度h_semaphore_wait(dispatch_semaphore_t dsema,dispatch_time_t timeout)
等候信号量。假如信号量值为0,那苹果范冰冰么该函数就会一源码交易平台向等候,也便是不回来(相当于阻塞当时线程),直到该函数等候时间复杂度的信号量的值大于等于1,该函数会对信号量的值进行初始化电脑减1操作,然后回来。 -
dispatch_semaphore_signal(dispatch_semaphore_t dsema)
发送信号量。该源码网站函数会对信号量的值进行加1操作。
经过这三个办法,就能操控GCD的最大并发数量。 事例:
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"1");
dispatch_semaphore_signal(sem);
});
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"2");
dispatch_semaphore_signal(sem);
});
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"3");
dispatch_semaphore_signal(sem);
});
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"4");
dispatch_semaphore_signal(sem);
});
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"5");
dispatch_semaphore_signal(sem);
});
这儿创立的便是一个为0信号量的比如,其实运转作用类似于串行行列。
信号量在运用的时分需求留意:
dispatch初始化英文_semaphore_wait 和 dispatch_semaphore_signal
一定要初始化英文成对出现。因为在信号量释放的时分,假如dsema_orig初始信号量的巨细大于dsema_value(经过dispatch_semaphore_wait和dispatch_semaphore_signal改动之后的信号量的巨细)就会触发溃散。
dispat源码时代ch_source
di初始化英文spatch_source
是⽤来监听事情的,能够创立不同类型的dispatch_source
来监听不同的事情。
dispatch_sou苹果手机怎么录屏rc
e能够监听的事情类型如下
:
dispatch_source
的⼏个⽅法:
事例:定时器
- (void)iTimer {
__block int timeout = 60;
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(_timer, ^{
if(timeout <= 0){
dispatch_source_cancel(_timer);
}
else{
timeout--;
NSLog(@"倒计时:%d", timeout);
}
});
dispatch_resume(_timer);
}