聲明:
1、如果文章内容涉及到其他已經發表了,但文章中又未提及轉載事項,請及時與本人聯系。
2、本文為個人了解,如果部分知識點與真實情況有出入,請忽略本文。
3、如本文解釋有任何問題導緻您的損失,概不負責。
4、本文是寫給小白的,大神可以忽略,或者提點意見,但是……不要(或者輕點)噴。
正文:
1 了解Block
1.1 概念
(1)帶有局部變量的匿名函數(代碼塊)。
(2)使用Blocks可以不聲明C++和Objective-C類,也沒有使用靜态變量、靜态全局變量或全局變量時的問題,僅用編寫C語言函數的源代碼量即可使用帶有局域變量的匿名函數。
1.2 文法
(1)^【傳回值類型】【(參數清單)】表達式
*其中“【】”内的内容為可省略内容。
(2)其中,傳回值類型、參數清單都可以省略。即使有傳回值,也可省略傳回值類型,編譯器會自動識别傳回值類型(NSObject或者void)。
例如:
^void (id testObj) {
testObj= [[NSString alloc] initWithString:@"This is a iOS Block test!"];
NSLog(@”%@”,testObj);
}
(3)建立Block,其實是系統自動建立了一個函數,而Block的指派其實就是将該函數的指針進行存儲、傳遞,類似函數指針指派(Block指派,下文會講到)。
2 Block的用法
2.1 Block類型變量
在Block文法下,可将Block代碼塊指派給Block類型的變量。即整個Block代碼塊可以作為“值”指派,指派對象為聲明為Block類型的變量。
2.1.1 以Block的傳回值作為指派對象
這種類型再熟悉不過,與普通的函數類似,将函數中return的值作為指派對象。
例如:
int testInt = ^int {
return7;
};
2.1.2 以Block作為指派對象
(1)在Block文法下,可将Block代碼塊指派給已聲明為Block類型的變量。
例如:
//聲明Block類型變量
int (^testBlk)(int);
//聲明Block類型變量,文法為“傳回值類型 (^Block代碼塊名稱)【(參數類型清單)】”
//将Block代碼塊指派給Block類型變量
testBlk = ^(int count){
returncount + 1;
};
(2)在Block文法下,可将Block代碼塊作為函數的傳遞參數。
例如:
void testFunction(Bool testBool, int (^testBlk)(int)){
if(testBool) {
testBlk;
}
}
(3)在Block文法下,可将Block代碼塊作為函數的傳回值。
例如:
int (^testBlk)(int) testFunction(){
return^(int count) { return count + 1;};
}
(4)用typedef聲明Block類型,利于代碼可讀性。
例如:
//聲明Block類型,作為Block的參數類型
typedef int (^testBlockType)(int);
int testInt = 0;
//作為傳遞參數時
void testFunction(testBlockType testBlk){
testBlk= ^(int count) { return count + 1;};
testInt= testBlk(10);
}
//作為傳回值時
testBlockType testFunction(){
return(^(int count) { return count + testInt;});
}
2.2 在Block中,截獲自動變量
在Block的代碼塊中,截獲代碼塊之外的變量,其變量值、使用方式須遵守Block文法的規則。
2.2.1截獲自動變量
(1)Block中,Block代碼塊截獲的自動變量值,是儲存在該自動變量的瞬間值。
例如:
int testInt = 0;
void (^blk)() = ^{printf(“value = %d”,testInt)};
blk();
//此處列印結果為:value = 0
testInt = 1;
blk();
//此處列印結果為:value = 0
(2)Block中,截獲自動變量後,不能改寫該變量的值。
例如:
int testInt = 0;
void (^blk)() = ^{ testInt = 1;};
blk();
//此處報錯。在Block代碼塊中,無法改寫非該Block内部自動變量的值。
2.2.2 __block說明符
如果需要在Block代碼塊中改寫該Block之外的自動變量的值,需要在該自動變量上附加__block說明符。
例如:
__block int testInt = 0;
void (^blk)() = ^{ testInt = 1;};
blk();
參考:
《Objective-C進階程式設計iOS與OS X多線程和記憶體管理》【日】KazukiSakamoto Tomohiko Furumoto 著 黎華 譯