版本:iOS13.5
source.h
注意:若有时handler不执行,是因为source被释放了,可以在回调中调用(void)dispatch_source_get_data(source);
或设为属性@property (nonatomic, strong) dispatch_source_t *source;
索引
- 创建一个新的调度源以监视低级系统对象,并响应事件自动将block回调提交给队列queue。
dispatch_source_create
- 为调度源source设置回调handler
dispatch_source_set_event_handler
- 为调度源source设置函数handler
dispatch_source_set_event_handler_f
- 为调度源source设置取消时调用的回调handler。
dispatch_source_set_cancel_handler
- 为调度源source设置取消时调用的函数handler。
dispatch_source_set_cancel_handler_f
- 异步取消调度源,以防止调用handler。
dispatch_source_cancel
- 返回与此调度源source关联的handle。
dispatch_source_get_handle
- 返回与此调度源source关联的mask。
dispatch_source_get_mask
- 返回调度源source的待处理数据
dispatch_source_get_data
- 将数据合并到调度源source中,并将handler提交到目标队列queue再执行。
dispatch_source_merge_data
- 设置计时器源的开始时间,间隔和回程值。
dispatch_source_set_timer
- 为调度源source设置激活后就调用的回调handler
dispatch_source_set_registration_handler
- 为调度源source设置激活后就调用的函数handler
dispatch_source_set_registration_handler_f
详解
- 创建一个新的调度源以监视低级系统对象,并响应事件自动将block回调提交给队列queue。
dispatch_source_t dispatch_source_create(dispatch_source_type_t type,
uintptr_t handle, unsigned long mask, dispatch_queue_t _Nullable queue);
该block回调通过dispatch_source_set_event_handler
和dispatch_source_set_event_handler_f
创建。
调度源创建后是非活跃的,设置好属性(handler, context)后需要调用dispatch_activate
或dispatch_resume
激活后才能响应事件。激活后就不能再调用dispatch_set_target_queue
和dispatch_activate
type 调度源的类型
handle mask 通过type来确定相应作用
queue 将block提交到的调度队列。如果队列为DISPATCH_TARGET_QUEUE_DEFAULT
,则源将block提交到默认优先级全局队列
//一个调度源,它合并调用dispatch_source_merge_data获得的数据,通过新增来合并数据。
//handle未使用(传0),mask未使用(传0)。
DISPATCH_SOURCE_TYPE_DATA_ADD
//一个调度源,它合并调用dispatch_source_merge_data获得的数据,通过按位或来合并数据。
//handle未使用(传0),mask未使用(传0)。
DISPATCH_SOURCE_TYPE_DATA_OR
//一个调度源,它跟踪调用dispatch_source_merge_data获得的数据。
//新获得的数据值将替换尚未传递给源回调的现有数据值。数据值为0将导致不调用回调。
//handle未使用(传0),mask未使用(传0)。
DISPATCH_SOURCE_TYPE_DATA_REPLACE
//一个调度源,它为死名通知监视Mach端口(dead name notifications 只能发送不能接收的通知)
//handle 具有发送或只能发送一次(mach_port_t)的Mach端口
//mask dispatch_source_mach_send_flags_t类型 见下面
DISPATCH_SOURCE_TYPE_MACH_SEND
//一个调度源,它为未处理消息监视Mach端口。
//handle 具有接收权限(mach_port_t)的Mach端口
//mask dispatch_source_mach_recv_flags_t类型 见下面 但当前未定义宏(传0)
DISPATCH_SOURCE_TYPE_MACH_RECV
//一个调度源,它为内存压力状况变化监视系统
//handle未使用(传0)
//mask dispatch_source_memorypressure_flags_t类型 见下面
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
//一个调度源,它为dispatch_source_proc_flags_t定义的事件监视外部进程
//handle 进程标识符(pid_t)
//mask dispatch_source_proc_flags_t类型 见下面
DISPATCH_SOURCE_TYPE_PROC
//一个调度源,它为可供读取的未处理字节监视文件描述符。
//handle 文件描述符(int)
//mask未使用(传0)
DISPATCH_SOURCE_TYPE_READ
//一个调度源,它为信号监视当前进程
//handle 信号编号(int)
//mask未使用(传0)
DISPATCH_SOURCE_TYPE_SIGNAL
//一个调度源,它基于计时器提交事件处理块
//handle未使用(传0)
//mask dispatch_source_timer_flags_t类型 见下面
DISPATCH_SOURCE_TYPE_TIMER
//一个调度源,它为由dispatch_source_vnode_flags_t定义的事件监视文件描述符
//handle 文件描述符(int)
//mask dispatch_source_vnode_flags_t类型 见下面
DISPATCH_SOURCE_TYPE_VNODE
//一个调度源,它为可用缓冲区空间去写入字节而监视文件描述符
//handle 文件描述符(int)
//mask未使用(传0)
DISPATCH_SOURCE_TYPE_WRITE
//破坏与发送权限相对应的接收权限
#define DISPATCH_MACH_SEND_DEAD 0x1
dispatch_source_mach_send_flags_t
//暂无定义的宏
dispatch_source_mach_recv_flags_t
//系统内存压力状况已恢复正常
#define DISPATCH_MEMORYPRESSURE_NORMAL 0x01
//系统内存压力状况已更改为警告。
#define DISPATCH_MEMORYPRESSURE_WARN 0x02
//系统内存压力状况已变为严重。
#define DISPATCH_MEMORYPRESSURE_CRITICAL 0x04
dispatch_source_memorypressure_flags_t
//该进程已经退出
#define DISPATCH_PROC_EXIT 0x80000000
//该进程已创建一个或多个子进程
#define DISPATCH_PROC_FORK 0x40000000
//通过exec()或posix_spawn(),该进程已成为另一个可执行映像。
#define DISPATCH_PROC_EXEC 0x20000000
//Unix信号已传递到该进程。
#define DISPATCH_PROC_SIGNAL 0x08000000
dispatch_source_proc_flags_t
//系统应尽最大努力严格遵守通过dispatch_source_set_timer
为计时器指定的回程值leeway
#define DISPATCH_TIMER_STRICT 0x1
dispatch_source_timer_flags_t;
//文件系统对象已从namespace中删除
#define DISPATCH_VNODE_DELETE 0x1
//文件系统对象数据已更改。
#define DISPATCH_VNODE_WRITE 0x2
//文件系统对象的大小已更改。
#define DISPATCH_VNODE_EXTEND 0x4
//文件系统对象元数据已更改
#define DISPATCH_VNODE_ATTRIB 0x8
//文件系统对象链接计数已更改。
#define DISPATCH_VNODE_LINK 0x10
//文件系统对象在namespace中被重命名。
#define DISPATCH_VNODE_RENAME 0x20
//文件系统对象被吊销
#define DISPATCH_VNODE_REVOKE 0x40
//文件系统对象已解锁。
#define DISPATCH_VNODE_FUNLOCK 0x100
dispatch_source_vnode_flags_t
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
- 为调度源source设置回调handler
void dispatch_source_set_event_handler(dispatch_source_t source,
dispatch_block_t _Nullable handler);
handler 提交给队列queue的回调typedef void (^dispatch_block_t)(void);
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"11");
});
- 为调度源source设置函数handler
void dispatch_source_set_event_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable handler);
handler 提交给队列queue的函数typedef void (*dispatch_function_t)(void *_Nullable);
函数handler要传递的参数通过dispatch_set_context
设置
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_event_handler_f(timer, handler);
void handler(void *context) {
NSLog(@"22");
}
- 为调度源source设置取消时调用的回调handler。
void dispatch_source_set_cancel_handler(dispatch_source_t source,
dispatch_block_t _Nullable handler);
handler 要提交到队列queue的回调
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_block_t block = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
NSLog(@"取消时的block");
});
dispatch_source_set_cancel_handler(timer, block);
- 为调度源source设置取消时调用的函数handler。
void dispatch_source_set_cancel_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable handler);
handler 要提交到队列queue的函数
函数handler要传递的参数通过dispatch_set_context
设置
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_cancel_handler_f(timer, handler);
void handler(void *context) {
NSLog(@"22");
}
- 异步取消调度源,以防止调用handler。
void dispatch_source_cancel(dispatch_source_t source);
不会取消正在运行的handler
- 测试调度源source是否已取消。
long dispatch_source_testcancel(dispatch_source_t source);
long 如果取消,则返回非0;如果未取消,则返回0。
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"11");
});
//因为创建的timer是未激活的 需要先激活才能操作
dispatch_activate(timer);
dispatch_source_cancel(timer);
long result = dispatch_source_testcancel(timer);
NSLog(@"%ld", result);
输出:
1
- 返回与此调度源source关联的handle。
uintptr_t dispatch_source_get_handle(dispatch_source_t source);
handle为dispatch_source_create
中传入的handle
- 返回与此调度源source关联的mask。
unsigned long dispatch_source_get_mask(dispatch_source_t source);
mask为dispatch_source_create
中传入的mask
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 1, 2, queue);
dispatch_source_set_event_handler(timer, ^{
NSLog(@"11");
});
//因为创建的timer是未激活的 需要先激活才能操作
dispatch_activate(timer);
long handle = dispatch_source_get_handle(timer);
long mask = dispatch_source_get_mask(timer);
NSLog(@"%ld %ld", handle, mask);
输出:
1 2
- 返回调度源source的待处理数据
unsigned long dispatch_source_get_data(dispatch_source_t source);
该函数应在handler中调用。在handler之外调用此函数的结果是不确定的。
long 返回的结果根据dispatch_source_create
传入的type而不同
* DISPATCH_SOURCE_TYPE_DATA_ADD: 应用定义的数据
* DISPATCH_SOURCE_TYPE_DATA_OR: 应用定义的数据
* DISPATCH_SOURCE_TYPE_DATA_REPLACE: 应用定义的数据
* DISPATCH_SOURCE_TYPE_MACH_SEND: dispatch_source_mach_send_flags_t
* DISPATCH_SOURCE_TYPE_MACH_RECV: dispatch_source_mach_recv_flags_t
* DISPATCH_SOURCE_TYPE_MEMORYPRESSURE dispatch_source_memorypressure_flags_t
* DISPATCH_SOURCE_TYPE_PROC: dispatch_source_proc_flags_t
* DISPATCH_SOURCE_TYPE_READ: 可读取的估计字节数
* DISPATCH_SOURCE_TYPE_SIGNAL: 自handler调用以来传递的信号数
* DISPATCH_SOURCE_TYPE_TIMER: 自handler调用以来计时器已触发的次数
* DISPATCH_SOURCE_TYPE_VNODE: dispatch_source_vnode_flags_t
* DISPATCH_SOURCE_TYPE_WRITE: 估计可用缓冲区空间
- 将数据合并到调度源source中,并将handler提交到目标队列queue再执行。
void dispatch_source_merge_data(dispatch_source_t source, unsigned long value);
该方法只支持dispatch_source_create
的 type为DISPATCH_SOURCE_TYPE_DATA_ADD
、DISPATCH_SOURCE_TYPE_DATA_OR
和DISPATCH_SOURCE_TYPE_DATA_REPLACE
的源
value 与待处理数据合并的值。传0时无效,也不会将handler提交到目标队列queue执行。
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
dispatch_source_set_event_handler(source, ^{
NSLog(@"source");
long data = dispatch_source_get_data(source);
NSLog(@"%ld", data);
});
dispatch_source_merge_data(source, 100);
dispatch_source_merge_data(source, 200);
dispatch_activate(source);
输出:
source
300
- 设置计时器源的开始时间,间隔和回程值。
void dispatch_source_set_timer(dispatch_source_t source, dispatch_time_t start,
uint64_t interval,uint64_t leeway);
该方法只支持dispatch_source_create
的 type为DISPATCH_SOURCE_TYPE_TIMER
的源
该方法会清除先前的计时器累积的所有未处理源数据。
如果定时器源已被取消,则调用此方法无效。
start 计时器下一次触发的时间
interval 每次触发的间隔 设为DISPATCH_TIME_FOREVER
表示只会调用一次
leeway 系统可能会延迟计时器的启动时间,以提高功耗和系统性能。允许延迟的上限可以用leeway参数配置,下限则由系统控制。
如果指定的计时器源是使用DISPATCH_TIMER_STRICT
的mask创建的,则系统将尽最大努力严格遵守所提供的leeway值,即使该值小于当前下限
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
(void)dispatch_source_get_data(timer);
NSLog(@"timer");
});
dispatch_resume(timer);
输出:
timer
timer
...
- 为调度源source设置激活后就调用的回调handler
void dispatch_source_set_registration_handler(dispatch_source_t source,
dispatch_block_t _Nullable handler);
如果在dispatch_resume
或dispatch_activate
之后调用该方法,那么handler将直接被提交到源的目标队列queue并执行
handler 提交到源的目标队列的回调
例:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
dispatch_source_set_registration_handler(source, ^{
NSLog(@"激活后回调");
});
dispatch_resume(source);
输出:
激活后回调
- 为调度源source设置激活后就调用的函数handler
void dispatch_source_set_registration_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable handler);
handler 提交到源的目标队列的函数
函数handler要传递的参数通过dispatch_set_context
设置
用法
用法1:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
dispatch_source_set_event_handler(source,^{
(void)dispatch_source_get_data(source);
NSLog(@"操作一次");
});
dispatch_resume(source);
//调用后会执行一次回调
dispatch_source_merge_data(source, 1);
输出:
操作一次
用法2:
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, queue);
dispatch_source_set_event_handler(source,^{
long data = dispatch_source_get_data(source);
NSLog(@"操作一次 %ld", data);
});
dispatch_resume(source);
dispatch_async(dispatch_get_main_queue(), ^{
for (NSInteger i = 1; i < 5; i++) {
dispatch_source_merge_data(source, i);
// [NSThread sleepForTimeInterval:0.1];
}
});
输出: 虽然执行了4次dispatch_source_merge_data,但会将data相加后只执行一次回调handler
操作一次 10
若取消注释[NSThread sleepForTimeInterval:0.1]
输出:则会执行多次block
操作一次 1
操作一次 2
操作一次 3
操作一次 4
用法3:
__block NSInteger timeout = 5;
dispatch_queue_t queue = dispatch_queue_create("source", DISPATCH_QUEUE_SERIAL);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, DISPATCH_TIMER_STRICT, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
(void)dispatch_source_get_data(timer);
if (timeout > 0) {
NSLog(@"倒计时%ld秒", timeout);
timeout--;
} else {
NSLog(@"倒计时结束");
dispatch_source_cancel(timer);
}
});
dispatch_activate(timer);
输出:
倒计时5秒
倒计时4秒
倒计时3秒
倒计时2秒
倒计时1秒
倒计时结束
网友评论