block.h
包含如下方法:
/*dispatch_block_flags_t 的枚舉*/
DISPATCH_ENUM(dispatch_block_flags, unsigned long,
DISPATCH_BLOCK_BARRIER
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x1,
DISPATCH_BLOCK_DETACHED
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x2,
DISPATCH_BLOCK_ASSIGN_CURRENT
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x4,
DISPATCH_BLOCK_NO_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x8,
DISPATCH_BLOCK_INHERIT_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x10,
DISPATCH_BLOCK_ENFORCE_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x20,
);
一寿羞、創(chuàng)建 block有兩個(gè)方法
/**
創(chuàng)建block方法
@param flags 用來設(shè)置 block 的標(biāo)記 (類型為 dispatch_block_flags_t 的枚舉)
@param block 用來設(shè)置具體的任務(wù)
@return 返回dispatch_block_t類型的block
*/
dispatch_block_t
dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
/**
創(chuàng)建block方法
@param flags 用來設(shè)置 block 的標(biāo)記
@param qos_class
@param relative_priority 優(yōu)先級(jí)
@param block 用來設(shè)置具體的任務(wù)
@return 返回dispatch_block_t類型的block
*/
dispatch_block_t
dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,
dispatch_qos_class_t qos_class, int relative_priority,dispatch_block_t block);
說明:dispatch_block_create_with_qos_class
相比于 dispatch_block_create
函數(shù),這種方式在創(chuàng)建 block 的同時(shí)可以指定了相應(yīng)的優(yōu)先級(jí)有勾。dispatch_qos_class_t
是 qos_class_t
的別名望伦,定義如下:
#if __has_include(<sys/qos.h>)
typedef qos_class_t dispatch_qos_class_t;
#else
typedef unsigned int dispatch_qos_class_t;
#endif
其中qos_class_t
是一個(gè)枚舉類型:
__QOS_ENUM(qos_class, unsigned int,
QOS_CLASS_USER_INTERACTIVE
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x21,
QOS_CLASS_USER_INITIATED
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x19,
QOS_CLASS_DEFAULT
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x15,
QOS_CLASS_UTILITY
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x11,
QOS_CLASS_BACKGROUND
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x09,
QOS_CLASS_UNSPECIFIED
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x00,
);
/*
1林说、QOS_CLASS_USER_INTERACTIVE
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x21,
表示任務(wù)會(huì)被立即執(zhí)行,在響應(yīng)事件之后更新 UI屯伞,來提供好的用戶體驗(yàn)腿箩。(不要放太耗時(shí)操作)。
2劣摇、QOS_CLASS_USER_INITIATED
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x19,
表示任務(wù)由 UI 發(fā)起異步執(zhí)行珠移。適用場景是需要獲取結(jié)果同時(shí)又可以繼續(xù)交互的時(shí)候。(不要放太耗時(shí)操作)
3末融、QOS_CLASS_DEFAULT
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x15,
默認(rèn)優(yōu)先級(jí) (不是給程序員使用的钧惧,用來重置對(duì)列使用的)
4、QOS_CLASS_UTILITY
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x11,
表示需要長時(shí)間運(yùn)行的任務(wù) (耗時(shí)操作勾习,可以使用這個(gè)選項(xiàng))
5浓瞪、QOS_CLASS_BACKGROUND
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x09,
表示用戶不需要知道任務(wù)什么時(shí)候完成。選擇這個(gè)選項(xiàng)速度慢得令人發(fā)指巧婶,非常不利于調(diào)試G洹(后臺(tái))
6、QOS_CLASS_UNSPECIFIED
__QOS_CLASS_AVAILABLE(macos(10.10), ios(8.0)) = 0x00,
未指定
*/
舉例說明:
dispatch_queue_t quene = dispatch_queue_create("com.Maker", DISPATCH_QUEUE_CONCURRENT);
dispatch_block_t qosBlock = dispatch_block_create_with_qos_class(0, QOS_CLASS_USER_INTERACTIVE, 0, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%@",[NSString stringWithFormat:@"qos_class 做一些事情..., %d",i]);
}
});
dispatch_async(quene, qosBlock);
dispatch_block_t block = dispatch_block_create(0, ^{
for (int i = 0; i < 100; i++) {
NSLog(@"%@",[NSString stringWithFormat:@"做一些事情..., %d",i]);
}
});
dispatch_async(quene, block);
二艺栈、監(jiān)聽任務(wù)(block)執(zhí)行
假如我們需要等待特定任務(wù)(block
) 執(zhí)行完成之后英岭,再去執(zhí)行其他任務(wù)(block
)。
可以通過兩種方式實(shí)現(xiàn):wait
和 notify
眼滤。
/**
等待block執(zhí)行
@param block 等待的block
@param timeout 等待時(shí)間 (DISPATCH_TIME_FOREVER巴席,這表示函數(shù)會(huì)一直等待 block 執(zhí)行完)
@return 返回long類型結(jié)果 (執(zhí)行 block 所需的時(shí)間小于 timeout,則返回 0诅需,否則返回非 0 值)
*/
long
dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);
/**
block通知
@param block 用來設(shè)置 block 的標(biāo)記
@param queue
@param notification_block
*/
void
dispatch_block_notify(dispatch_block_t block,
dispatch_queue_t queue,dispatch_block_t notification_block);
參數(shù)需要設(shè)置的 block 和等待時(shí)間 timeout漾唉。
timeout 參數(shù)表示函數(shù)在等待 block 執(zhí)行完畢時(shí),應(yīng)該等待多久堰塌。如果執(zhí)行 block 所需的時(shí)間小于 timeout赵刑,則返回 0,否則返回非 0 值场刑。此參數(shù)也可以取常量 DISPATCH_TIME_FOREVER
般此,這表示函數(shù)會(huì)一直等待 block 執(zhí)行完,而不會(huì)超時(shí)牵现☆戆茫可以使用 dispatch_time
函數(shù)和 DISPATCH_TIME_NOW
常量來方便的設(shè)置具體的超時(shí)時(shí)間。如果任務(wù)(block)執(zhí)行完成瞎疼,dispatch_block_wait
就會(huì)立即返回科乎。
注意不能使用 dispatch_block_wait
來等待同一個(gè) block 的多次執(zhí)行全部結(jié)束;這種情況可以考慮使用 dispatch_group_wait
來解決贼急。也不能在多個(gè)線程中茅茂,同時(shí)等待同一個(gè)任務(wù)(block)的結(jié)束。同一個(gè)任務(wù)(block)只能執(zhí)行一次太抓,被等待一次空闲。
注意:因?yàn)?dispatch_block_wait
會(huì)阻塞當(dāng)前線程,所以不應(yīng)該放在主線程中調(diào)用走敌。
實(shí)例說明一:
dispatch_queue_t quene = dispatch_queue_create("com.Maker", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(quene, ^{
dispatch_queue_t allTasksQueue = dispatch_queue_create("allTasksQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_block_t block = dispatch_block_create(0, ^{
NSLog(@"開始執(zhí)行");
sleep(3.0);
NSLog(@"結(jié)束執(zhí)行");
});
dispatch_async(allTasksQueue, block);
// 等待時(shí)長碴倾,10s 之后超時(shí)
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_FOREVER, (int64_t)(10 * NSEC_PER_SEC));
long resutl = dispatch_block_wait(block, timeout);
if (resutl == 0) {
NSLog(@"執(zhí)行成功");
} else {
NSLog(@"執(zhí)行超時(shí)");
}
});
實(shí)例說明二:
dispatch_queue_t allTasksQueue = dispatch_queue_create("allTasksQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_block_t block = dispatch_block_create(0, ^{
NSLog(@"開始執(zhí)行任務(wù)");
sleep(3.0);
NSLog(@"結(jié)束執(zhí)行任務(wù)");
});
dispatch_async(allTasksQueue, block);
dispatch_block_notify(block, allTasksQueue, ^{
NSLog(@"任務(wù)已經(jīng)執(zhí)行完畢");
});
三、取消任務(wù)(block)執(zhí)行
/**
取消任務(wù)(block)
@param block 指定取消的任務(wù)(block)
*/
void
dispatch_block_cancel(dispatch_block_t block);
/**
判斷任務(wù)(block)是否取消
@param block 指定任務(wù)(block)
@return 如果被取消非0掉丽,如果沒取消跌榔,則為0
*/
long
dispatch_block_testcancel(dispatch_block_t block);
舉例說明:
dispatch_queue_t queue = dispatch_queue_create("com.Maker", DISPATCH_QUEUE_SERIAL);
dispatch_block_t firstTask = dispatch_block_create(0, ^{
NSLog(@"開始第一個(gè)任務(wù)");
sleep(3.0);
NSLog(@"結(jié)束第一個(gè)任務(wù)");
});
dispatch_block_t secondTask = dispatch_block_create(0, ^{
NSLog(@"開始第二個(gè)任務(wù)");
sleep(4.0);
NSLog(@"結(jié)束第二個(gè)任務(wù)");
});
dispatch_async(queue, firstTask);
dispatch_async(queue, secondTask);
dispatch_block_cancel(firstTask);
NSLog(@"嘗試取消第一個(gè)任務(wù)");
long code = dispatch_block_testcancel(firstTask);
if (code == 0) {
NSLog(@"已經(jīng)開始執(zhí)行第一個(gè)任務(wù)");
}
else {
NSLog(@"已經(jīng)取消第一個(gè)任務(wù)");
}
dispatch_block_cancel(secondTask);
NSLog(@"嘗試取消第二個(gè)任務(wù)");