六、塊與大中樞派發(fā)
塊(block) 、大中樞派發(fā)(Grand center Dispatch, GCD)
語(yǔ)法閉包(lexical closure)
37.理解“塊”這一概念
- 塊石C、C++、Objective-C中的語(yǔ)法閉包
- 可以接受參數(shù)、返回值
- 根據(jù)范圍:“棧塊”、“堆塊”、“全局塊”。分配在棧上的塊可以拷貝到堆中,這樣的話就和標(biāo)準(zhǔn)的Objective-C對(duì)象一樣,具備引用計(jì)數(shù)能力。
基礎(chǔ)
塊的語(yǔ)法結(jié)構(gòu):
return_type (^block_name)(parameters)
一般應(yīng)用:
內(nèi)聯(lián)塊(inline block)直接內(nèi)聯(lián)在函數(shù)調(diào)用中使用。
numerateObjectsUsingBlock:
塊的內(nèi)部結(jié)構(gòu)
圖1
“棧塊”、“堆塊”、“全局塊”。
一開(kāi)始定義的塊其所占的內(nèi)唇區(qū)域是分配在棧內(nèi)。通過(guò)copy 就會(huì)分配到堆中。
全局塊:不會(huì)捕捉任何狀態(tài),運(yùn)行時(shí)也無(wú)須有狀態(tài)來(lái)參與。所使用的整個(gè)內(nèi)存區(qū)域,在編譯器已經(jīng)完全確定,全局塊可以聲明在全局內(nèi)存里。
38. 為常用的塊類型創(chuàng)建typedef
- 使用typedef重新定義塊類型,令塊變量用起來(lái)更加簡(jiǎn)單。
因?yàn)槊總€(gè)塊都具備“固有類型”(inherent type),因此可以賦給適當(dāng)類型的變量。
^(BOOL flag, int value){
if (flag) {
return value * 5;
}else{
return value * 10;
}
};
//變量類型以及賦值語(yǔ)句
int(^variableName)(BOOL flag, int value) = ^(BOOL flag, int value){
return 1;
};
variableName(YES, 10);
//塊類型的語(yǔ)法結(jié)構(gòu)
return_type (^block_name)(parameters)
使用C語(yǔ)言中“類型定義”(type definition)特性
例子:
typedef int(^EOCSomeBlock)(BooL flag, int value);
EOCSomeBlock block = ^(BOOL flag, int value){
//Implementation
}
block(YES, 10);
39.用handler 塊降低代碼分散程度
- 創(chuàng)建對(duì)象時(shí),可以使用內(nèi)聯(lián)的handler 塊將相關(guān)業(yè)務(wù)邏輯一并聲明。
- 在有多個(gè)實(shí)例需要監(jiān)控時(shí):
- 委托模式:需要經(jīng)常根據(jù)傳入的對(duì)象來(lái)切換
- 塊: 可以直接將相關(guān)塊和對(duì)象放在一起。
- 設(shè)計(jì)API的時(shí)候如果用到handler塊,可以增加一個(gè)參數(shù),通過(guò)這個(gè)參數(shù)來(lái)決定把塊安排到哪里隊(duì)列上執(zhí)行。<可能廢除了>
40.用塊引用其所屬對(duì)象時(shí)不要出現(xiàn)保留環(huán)
- 如果塊所捕獲的對(duì)象直接或間接保留了塊本身,那么就得當(dāng)心保留環(huán)問(wèn)題
- 一定要找個(gè)適當(dāng)?shù)臅r(shí)機(jī)解除保留環(huán)。
<weak, weakSelf, strongSelf>
41. 多用派發(fā)隊(duì)列,少用同步鎖
- 派發(fā)隊(duì)列可以用來(lái)表述同步語(yǔ)義,這種做法要比使用@synchronized塊 或者 NSLock 對(duì)象更簡(jiǎn)單
- 將同步與異步結(jié)合起來(lái),可以實(shí)現(xiàn)與普通加鎖機(jī)制一樣的同步方法,而這么做不會(huì)賭賽執(zhí)行異步派發(fā)的線程。
- 使用同步隊(duì)列柵欄塊,可以令同步行為更加高效。
42.多用GCD,少用performSelector
- 略
43.掌握GCD及操作隊(duì)列的使用時(shí)機(jī)
- 在解決多線程與任務(wù)管理問(wèn)題時(shí),派發(fā)隊(duì)列并非唯一方案。
- 操作隊(duì)列提供了一套高層的Objective-C API,能實(shí)現(xiàn)純GCD所具備的絕大部分功能,而且還能完成一些更為復(fù)雜的操作,那些操作若改用GCD來(lái)實(shí)現(xiàn),則需要另外編寫代碼。
44.通過(guò)Dispatch Group機(jī)制,根據(jù)系統(tǒng)資源狀況來(lái)執(zhí)行任務(wù)
- 一系列任務(wù)可歸入一個(gè)dispatch group 中。開(kāi)發(fā)者可以在這組任務(wù)執(zhí)行完畢時(shí)獲取通知。
- 通過(guò)dispatch group 可以在并發(fā)式派發(fā)隊(duì)列里同時(shí)執(zhí)行多項(xiàng)任務(wù)。GCD會(huì)根據(jù)系統(tǒng)資源狀況來(lái)調(diào)度這些并發(fā)執(zhí)行的任務(wù)。
45.使用dispatch_once來(lái)執(zhí)行只需要運(yùn)行一次的線程安全代碼
- 經(jīng)常需要編寫“只需執(zhí)行一次的線程安全代碼”(單例里)。通過(guò)GCD: dispatch_once 函數(shù),很容易就能實(shí)現(xiàn)此功能。
- 標(biāo)記應(yīng)該聲明在staic 或者 global 作用域中,這樣的話,在把值需要執(zhí)行一次的塊傳給 dispatch_once 函數(shù)時(shí),傳如的標(biāo)記也是相同的。
46.不要使用dispatch_get_current_queue
-略