什么是Dispatch Source
dispatch source是一个检视某类事件的对象,当这些事件发生时,将自动把一个代码块放入指定的队列中执行处理事件
dispatch source是基础数据类型,协调底层系统事件的的处理
dispatch source的某类事件包括
timer dispatch source 定期产生通知
signal dispatch source UNIX信号到达时产生通知descriptor dispatch source各种文件和socket操作的通知
process dispatch source 进程相关的事件通知Mach port dispatch sourceMach相关事件的通知custom dispatch source 自己定义并自己触发
dispatch source替代了异步回调函数,来处理系统相关的事件。配置一个dispatch source的时候需要指定一个检视的事件、事件发生时处理的GCD队列、事件处理的代码块
为了防止事件积压到dispatch queue,dispatch source实现了事件合并机制。如果新事件在上一个事件处理器出列并执行之前到达,dispatch source会将新旧事件的数据合并。根据事件类型的不同,合并操作可能会替换旧事件,或者更新旧事件的信息
BB了这么多,讲一下怎么用吧
dispatch_source_create(dispatch_source_type_t _Nonnull type, uintptr_t handle, unsigned long mask, dispatch_queue_t _Nullable queue)
参数说明
dispatch_source_type_t type 自定义事件,变量增加
uintptr_t handle 可以理解为句柄、索引或id,假如要监听进程,需要传入进程的ID
long mask 可以理解为描述,提供更详细的描述,让它知道具体要监听什么dispatch_queue_t _Nullable queue 自定义源需要的一个队列,用来处理所触发的事件代码
1.dispatch_source_type_t 这个类型的参数可传
参数说明
DISPATCH_SOURCE_TYPE_DATA_ADD 自定义事件,变量增加
DISPATCH_SOURCE_TYPE_DATA_OR 自定义事件,变or
DISPATCH_SOURCE_TYPE_MACH_SEND Mach端口发送
DISPATCH_SOURCE_TYPE_MACH_RECV Mach端口接收
DISPATCH_SOURCE_TYPE_PROC 进程监听,如京城的推出、创建一个更多的至县城、进程受到UNIX信号
DISPATCH_SOURCE_TYPE_READ IO操作,如对文件的操作、socket操作的读响应DISPATCH_SOURCE_TYPE_SIGNAL 接收到UNIX信号时响应DISPATCH_SOURCE_TYPE_TIMER定时器DISPATCH_SOURCE_TYPE_WRITE IO操作,如对文件的操作、socket操作的写响应
dispatch source相关的函数
dispatch_suspend(queue)
挂起队列
dispatch_resume(source)
分派源创建时默认处于暂停状态,在分派源分派处理程序之前必须先恢复
dispatch_source_merge_data
向分派源发送事件,需要注意的是,不可以传递0值(事件不会被触发),同样也不可以传递负数。 dispatch_source_set_event_handler 设置响应分派源事件的block,在分派源指定的队列上运行
dispatch_source_get_data
得到分派源的数据
uintptr_t dispatch_source_get_handle(dispatch_source_t source)
得到dispatch源创建,即调用dispatch_source_create的第二个参数
unsigned long dispatch_source_get_mask(dispatch_source_t source)
得到dispatch源创建,即调用dispatch_source_create的第三个参数
void dispatch_source_cancel(dispatch_source_t source)
取消dispatch源的事件处理--即不再调用block。如果调用dispatch_suspend只是暂停dispatch源。 long dispatch_source_testcancel(dispatch_source_t source)
检测是否dispatch源被取消,如果返回非0值则表明dispatch源已经被取消
void dispatch_source_set_cancel_handler(dispatch_source_t source, dispatch_block_t cancel_handler)
dispatch源取消时调用的block,一般用于关闭文件或socket等,释放相关资源
void dispatch_source_set_registration_handler(dispatch_source_t source, dispatch_block_t registration_handler)
可用于设置dispatch源启动时调用block,调用完成后即释放这个block。也可在dispatch源运行当中随时调用这个函数。
不同的监视事件有不同的处理方式
定时器:
__block int count = 20;
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(timer, ^{
label.text = @(count/100.0).stringValue;
if (count<=0) {
dispatch_source_cancel(timer);
}
count--;
});
dispatch_resume(timer);
配置dispatch_source_set_timer函数参数一共有四个
参数说明dispatch_source_t _Nonnull source需要配置的dispatch source 分派源dispatch_time_t start开始时间,dispatch_time也需要两个参数下面讲解uint64_t interval时间间隔、如果传入DISPATCH_TIME_FOREVER表示永不重复uint64_t leeway精确度,默认传0就ok
dispatch_time_t函数,表示的事一个时间其中需要传递两个参数
第一个固定写法DISPATCH_TIME_NOW或者DISPATCH_TIME_FOREVER,从字面意思可以看得出来前者是现在开始,后者是永远不重复
第二个参数是一个时间单位
NSEC_PER_SEC 1000000000ull 秒
NSEC_PER_MSEC 1000000ull 毫秒
比如:
dispatch_time(DISPATCH_TIME_NOW,3.0*NSEC_PER_SEC);
意思是从现在的过后的第三秒
多线程通信:
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
dispatch_source_set_event_handler(source, ^{
//主线程操作
NSLog(@"%ld",(long)[NSDate date].timeIntervalSince1970);
NSLog(@"%ld",dispatch_source_get_data(source));
//关闭监视源
dispatch_source_cancel(source);
});
dispatch_resume(source);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//子线程耗时操作
NSLog(@"%ld",(long)[NSDate date].timeIntervalSince1970);
sleep(3.0);
dispatch_source_merge_data(source, 2); //通知队列
});
其他的在开发中基本上也用不到,这里作者大大就不讲解了
网友评论