版本:iOS13.5
source.h
注意:若有時(shí)handler不執(zhí)行,是因?yàn)閟ource被釋放了,可以在回調(diào)中調(diào)用(void)dispatch_source_get_data(source);或設(shè)為屬性@property (nonatomic, strong) dispatch_source_t *source;
索引
- 創(chuàng)建一個(gè)新的調(diào)度源以監(jiān)視低級(jí)系統(tǒng)對(duì)象,并響應(yīng)事件自動(dòng)將block回調(diào)提交給隊(duì)列queue。
dispatch_source_create - 為調(diào)度源source設(shè)置回調(diào)handler
dispatch_source_set_event_handler - 為調(diào)度源source設(shè)置函數(shù)handler
dispatch_source_set_event_handler_f - 為調(diào)度源source設(shè)置取消時(shí)調(diào)用的回調(diào)handler。
dispatch_source_set_cancel_handler - 為調(diào)度源source設(shè)置取消時(shí)調(diào)用的函數(shù)handler。
dispatch_source_set_cancel_handler_f - 異步取消調(diào)度源,以防止調(diào)用handler。
dispatch_source_cancel - 返回與此調(diào)度源source關(guān)聯(lián)的handle。
dispatch_source_get_handle - 返回與此調(diào)度源source關(guān)聯(lián)的mask。
dispatch_source_get_mask - 返回調(diào)度源source的待處理數(shù)據(jù)
dispatch_source_get_data - 將數(shù)據(jù)合并到調(diào)度源source中,并將handler提交到目標(biāo)隊(duì)列queue再執(zhí)行。
dispatch_source_merge_data - 設(shè)置計(jì)時(shí)器源的開始時(shí)間,間隔和回程值。
dispatch_source_set_timer - 為調(diào)度源source設(shè)置激活后就調(diào)用的回調(diào)handler
dispatch_source_set_registration_handler - 為調(diào)度源source設(shè)置激活后就調(diào)用的函數(shù)handler
dispatch_source_set_registration_handler_f
詳解
- 創(chuàng)建一個(gè)新的調(diào)度源以監(jiān)視低級(jí)系統(tǒng)對(duì)象,并響應(yīng)事件自動(dòng)將block回調(diào)提交給隊(duì)列queue。
dispatch_source_t dispatch_source_create(dispatch_source_type_t type,
uintptr_t handle, unsigned long mask, dispatch_queue_t _Nullable queue);
該block回調(diào)通過(guò)dispatch_source_set_event_handler和dispatch_source_set_event_handler_f創(chuàng)建。
調(diào)度源創(chuàng)建后是非活躍的,設(shè)置好屬性(handler, context)后需要調(diào)用dispatch_activate或dispatch_resume激活后才能響應(yīng)事件。激活后就不能再調(diào)用dispatch_set_target_queue和dispatch_activate
type 調(diào)度源的類型
handle mask 通過(guò)type來(lái)確定相應(yīng)作用
queue 將block提交到的調(diào)度隊(duì)列。如果隊(duì)列為DISPATCH_TARGET_QUEUE_DEFAULT,則源將block提交到默認(rèn)優(yōu)先級(jí)全局隊(duì)列
//一個(gè)調(diào)度源,它合并??調(diào)用dispatch_source_merge_data獲得的數(shù)據(jù),通過(guò)新增來(lái)合并數(shù)據(jù)。
//handle未使用(傳0),mask未使用(傳0)。
DISPATCH_SOURCE_TYPE_DATA_ADD
//一個(gè)調(diào)度源,它合并??調(diào)用dispatch_source_merge_data獲得的數(shù)據(jù),通過(guò)按位或來(lái)合并數(shù)據(jù)。
//handle未使用(傳0),mask未使用(傳0)。
DISPATCH_SOURCE_TYPE_DATA_OR
//一個(gè)調(diào)度源,它跟蹤調(diào)用dispatch_source_merge_data獲得的數(shù)據(jù)。
//新獲得的數(shù)據(jù)值將替換尚未傳遞給源回調(diào)的現(xiàn)有數(shù)據(jù)值。數(shù)據(jù)值為0將導(dǎo)致不調(diào)用回調(diào)。
//handle未使用(傳0),mask未使用(傳0)。
DISPATCH_SOURCE_TYPE_DATA_REPLACE
//一個(gè)調(diào)度源,它為死名通知監(jiān)視Mach端口(dead name notifications 只能發(fā)送不能接收的通知)
//handle 具有發(fā)送或只能發(fā)送一次(mach_port_t)的Mach端口
//mask dispatch_source_mach_send_flags_t類型 見(jiàn)下面
DISPATCH_SOURCE_TYPE_MACH_SEND
//一個(gè)調(diào)度源,它為未處理消息監(jiān)視Mach端口。
//handle 具有接收權(quán)限(mach_port_t)的Mach端口
//mask dispatch_source_mach_recv_flags_t類型 見(jiàn)下面 但當(dāng)前未定義宏(傳0)
DISPATCH_SOURCE_TYPE_MACH_RECV
//一個(gè)調(diào)度源,它為內(nèi)存壓力狀況變化監(jiān)視系統(tǒng)
//handle未使用(傳0)
//mask dispatch_source_memorypressure_flags_t類型 見(jiàn)下面
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
//一個(gè)調(diào)度源,它為dispatch_source_proc_flags_t定義的事件監(jiān)視外部進(jìn)程
//handle 進(jìn)程標(biāo)識(shí)符(pid_t)
//mask dispatch_source_proc_flags_t類型 見(jiàn)下面
DISPATCH_SOURCE_TYPE_PROC
//一個(gè)調(diào)度源,它為可供讀取的未處理字節(jié)監(jiān)視文件描述符。
//handle 文件描述符(int)
//mask未使用(傳0)
DISPATCH_SOURCE_TYPE_READ
//一個(gè)調(diào)度源,它為信號(hào)監(jiān)視當(dāng)前進(jìn)程
//handle 信號(hào)編號(hào)(int)
//mask未使用(傳0)
DISPATCH_SOURCE_TYPE_SIGNAL
//一個(gè)調(diào)度源,它基于計(jì)時(shí)器提交事件處理塊
//handle未使用(傳0)
//mask dispatch_source_timer_flags_t類型 見(jiàn)下面
DISPATCH_SOURCE_TYPE_TIMER
//一個(gè)調(diào)度源,它為由dispatch_source_vnode_flags_t定義的事件監(jiān)視文件描述符
//handle 文件描述符(int)
//mask dispatch_source_vnode_flags_t類型 見(jiàn)下面
DISPATCH_SOURCE_TYPE_VNODE
//一個(gè)調(diào)度源,它為可用緩沖區(qū)空間去寫入字節(jié)而監(jiān)視文件描述符
//handle 文件描述符(int)
//mask未使用(傳0)
DISPATCH_SOURCE_TYPE_WRITE
//破壞與發(fā)送權(quán)限相對(duì)應(yīng)的接收權(quán)限
#define DISPATCH_MACH_SEND_DEAD 0x1
dispatch_source_mach_send_flags_t
//暫無(wú)定義的宏
dispatch_source_mach_recv_flags_t
//系統(tǒng)內(nèi)存壓力狀況已恢復(fù)正常
#define DISPATCH_MEMORYPRESSURE_NORMAL 0x01
//系統(tǒng)內(nèi)存壓力狀況已更改為警告。
#define DISPATCH_MEMORYPRESSURE_WARN 0x02
//系統(tǒng)內(nèi)存壓力狀況已變?yōu)閲?yán)重。
#define DISPATCH_MEMORYPRESSURE_CRITICAL 0x04
dispatch_source_memorypressure_flags_t
//該進(jìn)程已經(jīng)退出
#define DISPATCH_PROC_EXIT 0x80000000
//該進(jìn)程已創(chuàng)建一個(gè)或多個(gè)子進(jìn)程
#define DISPATCH_PROC_FORK 0x40000000
//通過(guò)exec()或posix_spawn(),該進(jìn)程已成為另一個(gè)可執(zhí)行映像。
#define DISPATCH_PROC_EXEC 0x20000000
//Unix信號(hào)已傳遞到該進(jìn)程。
#define DISPATCH_PROC_SIGNAL 0x08000000
dispatch_source_proc_flags_t
//系統(tǒng)應(yīng)盡最大努力嚴(yán)格遵守通過(guò)dispatch_source_set_timer為計(jì)時(shí)器指定的回程值leeway
#define DISPATCH_TIMER_STRICT 0x1
dispatch_source_timer_flags_t;
//文件系統(tǒng)對(duì)象已從namespace中刪除
#define DISPATCH_VNODE_DELETE 0x1
//文件系統(tǒng)對(duì)象數(shù)據(jù)已更改。
#define DISPATCH_VNODE_WRITE 0x2
//文件系統(tǒng)對(duì)象的大小已更改。
#define DISPATCH_VNODE_EXTEND 0x4
//文件系統(tǒng)對(duì)象元數(shù)據(jù)已更改
#define DISPATCH_VNODE_ATTRIB 0x8
//文件系統(tǒng)對(duì)象鏈接計(jì)數(shù)已更改。
#define DISPATCH_VNODE_LINK 0x10
//文件系統(tǒng)對(duì)象在namespace中被重命名。
#define DISPATCH_VNODE_RENAME 0x20
//文件系統(tǒng)對(duì)象被吊銷
#define DISPATCH_VNODE_REVOKE 0x40
//文件系統(tǒng)對(duì)象已解鎖。
#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);
- 為調(diào)度源source設(shè)置回調(diào)handler
void dispatch_source_set_event_handler(dispatch_source_t source,
dispatch_block_t _Nullable handler);
handler 提交給隊(duì)列queue的回調(diào)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");
});
- 為調(diào)度源source設(shè)置函數(shù)handler
void dispatch_source_set_event_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable handler);
handler 提交給隊(duì)列queue的函數(shù)typedef void (*dispatch_function_t)(void *_Nullable);
函數(shù)handler要傳遞的參數(shù)通過(guò)dispatch_set_context設(shè)置
例:
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");
}
- 為調(diào)度源source設(shè)置取消時(shí)調(diào)用的回調(diào)handler。
void dispatch_source_set_cancel_handler(dispatch_source_t source,
dispatch_block_t _Nullable handler);
handler 要提交到隊(duì)列queue的回調(diào)
例:
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(@"取消時(shí)的block");
});
dispatch_source_set_cancel_handler(timer, block);
- 為調(diào)度源source設(shè)置取消時(shí)調(diào)用的函數(shù)handler。
void dispatch_source_set_cancel_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable handler);
handler 要提交到隊(duì)列queue的函數(shù)
函數(shù)handler要傳遞的參數(shù)通過(guò)dispatch_set_context設(shè)置
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");
}
- 異步取消調(diào)度源,以防止調(diào)用handler。
void dispatch_source_cancel(dispatch_source_t source);
不會(huì)取消正在運(yùn)行的handler
- 測(cè)試調(diào)度源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");
});
//因?yàn)閯?chuàng)建的timer是未激活的 需要先激活才能操作
dispatch_activate(timer);
dispatch_source_cancel(timer);
long result = dispatch_source_testcancel(timer);
NSLog(@"%ld", result);
輸出:
1
- 返回與此調(diào)度源source關(guān)聯(lián)的handle。
uintptr_t dispatch_source_get_handle(dispatch_source_t source);
handle為dispatch_source_create中傳入的handle
- 返回與此調(diào)度源source關(guān)聯(lián)的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");
});
//因?yàn)閯?chuàng)建的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
- 返回調(diào)度源source的待處理數(shù)據(jù)
unsigned long dispatch_source_get_data(dispatch_source_t source);
該函數(shù)應(yīng)在handler中調(diào)用。在handler之外調(diào)用此函數(shù)的結(jié)果是不確定的。
long 返回的結(jié)果根據(jù)dispatch_source_create傳入的type而不同
* DISPATCH_SOURCE_TYPE_DATA_ADD: 應(yīng)用定義的數(shù)據(jù)
* DISPATCH_SOURCE_TYPE_DATA_OR: 應(yīng)用定義的數(shù)據(jù)
* DISPATCH_SOURCE_TYPE_DATA_REPLACE: 應(yīng)用定義的數(shù)據(jù)
* 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: 可讀取的估計(jì)字節(jié)數(shù)
* DISPATCH_SOURCE_TYPE_SIGNAL: 自handler調(diào)用以來(lái)傳遞的信號(hào)數(shù)
* DISPATCH_SOURCE_TYPE_TIMER: 自handler調(diào)用以來(lái)計(jì)時(shí)器已觸發(fā)的次數(shù)
* DISPATCH_SOURCE_TYPE_VNODE: dispatch_source_vnode_flags_t
* DISPATCH_SOURCE_TYPE_WRITE: 估計(jì)可用緩沖區(qū)空間
- 將數(shù)據(jù)合并到調(diào)度源source中,并將handler提交到目標(biāo)隊(duì)列queue再執(zhí)行。
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 與待處理數(shù)據(jù)合并的值。傳0時(shí)無(wú)效,也不會(huì)將handler提交到目標(biāo)隊(duì)列queue執(zhí)行。
例:
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
- 設(shè)置計(jì)時(shí)器源的開始時(shí)間,間隔和回程值。
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的源
該方法會(huì)清除先前的計(jì)時(shí)器累積的所有未處理源數(shù)據(jù)。
如果定時(shí)器源已被取消,則調(diào)用此方法無(wú)效。
start 計(jì)時(shí)器下一次觸發(fā)的時(shí)間
interval 每次觸發(fā)的間隔 設(shè)為DISPATCH_TIME_FOREVER表示只會(huì)調(diào)用一次
leeway 系統(tǒng)可能會(huì)延遲計(jì)時(shí)器的啟動(dòng)時(shí)間,以提高功耗和系統(tǒng)性能。允許延遲的上限可以用leeway參數(shù)配置,下限則由系統(tǒng)控制。
如果指定的計(jì)時(shí)器源是使用DISPATCH_TIMER_STRICT的mask創(chuàng)建的,則系統(tǒng)將盡最大努力嚴(yán)格遵守所提供的leeway值,即使該值小于當(dāng)前下限
例:
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
...
- 為調(diào)度源source設(shè)置激活后就調(diào)用的回調(diào)handler
void dispatch_source_set_registration_handler(dispatch_source_t source,
dispatch_block_t _Nullable handler);
如果在dispatch_resume或dispatch_activate之后調(diào)用該方法,那么handler將直接被提交到源的目標(biāo)隊(duì)列queue并執(zhí)行
handler 提交到源的目標(biāo)隊(duì)列的回調(diào)
例:
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(@"激活后回調(diào)");
});
dispatch_resume(source);
輸出:
激活后回調(diào)
- 為調(diào)度源source設(shè)置激活后就調(diào)用的函數(shù)handler
void dispatch_source_set_registration_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable handler);
handler 提交到源的目標(biāo)隊(duì)列的函數(shù)
函數(shù)handler要傳遞的參數(shù)通過(guò)dispatch_set_context設(shè)置
用法
用法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);
//調(diào)用后會(huì)執(zhí)行一次回調(diào)
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];
}
});
輸出: 雖然執(zhí)行了4次dispatch_source_merge_data,但會(huì)將data相加后只執(zhí)行一次回調(diào)handler
操作一次 10
若取消注釋[NSThread sleepForTimeInterval:0.1]
輸出:則會(huì)執(zhí)行多次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(@"倒計(jì)時(shí)%ld秒", timeout);
timeout--;
} else {
NSLog(@"倒計(jì)時(shí)結(jié)束");
dispatch_source_cancel(timer);
}
});
dispatch_activate(timer);
輸出:
倒計(jì)時(shí)5秒
倒計(jì)時(shí)4秒
倒計(jì)時(shí)3秒
倒計(jì)時(shí)2秒
倒計(jì)時(shí)1秒
倒計(jì)時(shí)結(jié)束