Effective Object-C 52:37-46

六、塊與大中樞派發(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í):
    1. 委托模式:需要經(jīng)常根據(jù)傳入的對(duì)象來(lái)切換
    2. 塊: 可以直接將相關(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

-略

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容