第六章 塊(Block)與大中樞派發(fā)(Grand Central Dispatch,GCD)

總結(jié)

一、理解“塊”這一概念

1、塊的基礎(chǔ)知識(shí)

(1)、概念:

塊用“^”符號(hào)來(lái)表示,后面跟著一對(duì)花括號(hào),括號(hào)里面是塊的實(shí)現(xiàn)代碼。例如:

^{
    // Block implementation here
}

塊其實(shí)就是個(gè)值,也有其相關(guān)類型,可以把塊賦給變量并使用它。塊類型的語(yǔ)法與函數(shù)指針近似。例如,無(wú)參數(shù)無(wú)返回值的塊類型定義如下:

void (^someBlock)() = ^{
        //  Block implementation here
};

因此,我們可以把塊類型的語(yǔ)法結(jié)構(gòu)寫(xiě)成這樣子,如下:

return_type (^block_name) (parameters)

例子:

int (^addBlock) (int a, int b) = ^(int a, int b) {
    return a + b;
};

(2)、塊的內(nèi)部結(jié)構(gòu)

塊本身也是對(duì)象,在存放塊對(duì)象的內(nèi)存區(qū)域中,首個(gè)變量是指向Class對(duì)象的指針(isa),下圖描述了塊對(duì)象的內(nèi)存布局。


WechatIMG156.jpeg

在內(nèi)存布局中,最重要的就是invoke變量,這是個(gè)函數(shù)指針,指向塊的實(shí)現(xiàn)代碼。

(3)、全局塊、棧塊及堆塊

定義塊的時(shí)候,其所占的內(nèi)存區(qū)域是分配在棧中的。
若要在塊定義的范圍之外使用,則需給塊對(duì)象發(fā)送copy消息以拷貝之,這樣就把塊從棧復(fù)制到堆了,拷貝后的塊就可以在定義它的那個(gè)范圍之外使用了。
塊也可以定義成全局的。

2、為常用的塊類型創(chuàng)建typedef

為了隱藏復(fù)雜的塊類型,需要使用類型定義,如:

typedef int (^EOCSomeBlock) (BOOL flag, int value);
EOCSomeBlock block = ^(BOOL flag, int value) {
    //Implementation
};

3、用 handler 塊降低代碼分散程度

在程序里使用delegate的地方都可以使用Block來(lái)替換,其使用方法如下:

typedef void (^EOCNetworkFetcherCompletionHandler) (NSData *data, NSError *error);

@interface EOCNetworkFetcher : NSObject
- (void)startWithCompletionHandler:(EOCNetworkFetcherCompletionHandler)handler;
@end

4、用塊引用其所屬對(duì)象時(shí)不要出現(xiàn)保留環(huán)

1、如果塊所捕獲的對(duì)象直接或間接地保留了塊本身,那么久得當(dāng)心保留環(huán)的問(wèn)題。
2、一定要找個(gè)適當(dāng)?shù)臅r(shí)機(jī)解除保留環(huán)。

5、多用派發(fā)隊(duì)列,少用同步鎖

1、有種簡(jiǎn)單而高效的辦法可以代替同步塊或鎖對(duì)象,那就是使用“串行同步隊(duì)列”。

dispatch_queue_t  _syncQueue = dispatch_queue_create("com.effectiveobjectivec.syncQueue", NULL);
- (NSString *)someString {
  __block NSString *localSomeString;
  dispatch_sync(_syncQueue, ^{
       localSomeString = _someString;
  });
  return localSomeString;
}

- (void)setSomeString:(NSString *)someString {
    dispatch_sync(_syncQueue, ^{
        _someString = someString;
    });
}

進(jìn)一步優(yōu)化,可以將設(shè)置實(shí)例變量的方法中所用到的塊同步改成異步:dispatch_async(_syncQueue, ^{});

?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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