本系列文章主要是對《Objective-C 高級編程》這本書作的讀書筆記總結,除了這本書中的內容之外,也加上了本身對開發技術的理解和一些我的的經驗分享。編程
Blocks是C語言的擴充功能,是帶有局部變量的匿名函數(匿名其實就是沒有名稱的函數,C語言標準不容許匿名函數)函數
例如:這裏聲明瞭一個名稱爲func的函數指針
int func (int count);
爲了調用該函數,必須使用該函數的名稱code
int result = func (10);
若是像下面這樣,使用函數指針來代替直接調用函數,那麼不須要使用函數名也可以使用該函數開發
int result = (*funcPtr) (10);
但其實使用函數指針也仍然須要知道函數名稱。例如如下,在賦值給函數指針時,若不使用函數的名稱,就取法取得該函數的地址。it
int (*funcPtr)(int) = &func; int result = (*funcPtr) (10);
而經過Blocks,源代碼中就可以使用匿名函數。編譯
匿名函數你們已經知道了,那麼如今讓咱們來看一下C語言中可能使用的變量有哪些 :table
下面咱們來詳細講解一下帶有局部變量值的匿名函數Blocks的語法:匿名函數
^
返回值類型
參數列表
表達式
讀書筆記
如下定義代表這是一個表示沒有返回類型,而且參數爲int型的Block ^ void (int a, int b) { // do sth }
如上所示:完整形式的Blocks和C語言的函數定義區別爲:
^
舒適小貼士:由於OS X,iOS 應用程序的源代碼中大量使用Block,因此插入該記號便於查找。
block能夠省略返回類型
省略返回類型的語法爲: ^
參數列表
表達式
^ void (int a, int b) {表達式} 等價於 ^ (int a, int b) {表達式}
其次,若是不使用參數,block也能夠省略參數列表
語法爲: ^
表達式
^ { // 說點什麼吧,少年 }
int func (int count) { return count + 1; } // 函數func的地址賦值給函數指針變量funcPtr // 在block語法下可將block賦值給聲明爲block類型的變量 int (*funcPtr) (int) = &func
int (^blockName) (int)
與前面的使用函數指針的源代碼對比可知,聲明block類型變量僅僅是將聲明函數指針類型變量 *
變爲 ^
int (^block) (int) = ^ (int count) { return count + 1; }
block類型變量與c語言變量相同,block也能夠做爲函數參數傳遞或者函數的返回值
void func ( int (^block) (int) ) { // }
int (^func()) (int) { // return ^ (int count) { return count + 1; }; }
由上面源代碼能夠看出在使用block變量時,記錄方式很是複雜。咱們能夠像使用函數指針類型那樣,使用 typedef
來解決
typedef int (block_t) (int)
咱們來對比如下
// 沒有定義前 void func ( int (^block) (int) ) { } // 定義後 void func (block_t block) { }
另外,Block調用 和 C語言中使用函數指針調用函數的方法幾乎徹底相同。
int result = (*funcPtr)(10);
int result = block(10);
也可使用指向block類型變量的指針調用block
typedef int (^block_t) (int) block_t block = ^ (int count) { return count + 1; } block_t *blockPtr = █ (* blockPtr)(10);
截獲局部變量值 是指保存執行block語法瞬間的值,而且保存後就不能修改變量值。
int val = 0; void (^block) (void) = ^ { NSLog(@"val = %d", val); } val = 1; block();
執行上面源代碼,打印val的值爲0。這是由於在block中截獲了局部變量的值,即保存了該變量的瞬間值。因此即便更改了變量的值也不會影響block的打印。
執行下面源代碼,會產生編譯錯誤。
int val = 0; void (^block) (void) = ^ { val = 1; } block(); NSLog(@"val = %d", val);
向截獲的變量直接賦值會發生編譯錯誤,但使用截獲的值卻不會報錯。
id array = [NSMutableArray array]; void (^block) (void) = ^ { id obj = [[NSObject alloc] init]; [array addObject:obj]; } block();
若想在block中修改局部變量的值,須要在該自動變量前加 __block
說明符。
__block int val = 0; void (^block) (void) = ^ { val = 1; } block(); NSLog(@"val = %d", val);
源代碼的執行結果爲:val = 1