Block Objects 學習筆記
Block 對象集合了面向對象程式設計和面向過程程式設計的特點。可以把Block是一種類型,可以擁有執行個體對象,可以用某個指針變量指向一個BLOCK對象。指向Block類型的對象的變量有變量名和類型。如下代碼:
NSString * string;
其中NSString *是類型,string是變量名。隻是聲明的文法稍有不同,如下代碼:
int (^ adder)(int a, int b);
adder是Block的變量名,其中符号^代表該變量是Block類型變量。前面的int表示該對象(adder)的傳回類型是int,後面的(int a,int b)表示該對想帶有兩個int類型的參數。
如下代碼:
^int(int x, int y){
return x + y;
};
隻是建立了一個Block,傳回值是int類型。通常情況下,應該将建立的block立刻賦給某個Block的變量,如下:
int (^adder)(int, int) = ^int(int x, int y){
return x + y;
};
執行Block對象時,可以像c調用函數那樣調用Block變量,代碼如下:
int (^adder)(int, int) = ^int(int x, int y){
return x + y;
};
int sum = adder(2, 5);
NSLog(@"%i",sum);
輸出結果7
Block有一個很好的特性:它能捕獲變量。
首先了解Block對象的封閉作用域:對聲明了某個Block的對象方法,該方法的作用域就是這個Block的對象的封閉作用域。是以該Block可以通路該方法的所有局部變量、傳入該方法的實參以及傳入目前對象的執行個體變量。
如下代碼:
@interface Test1: NSObject
@property (nonatomic, copy) int (^testBlock)(int, int);
- (void) setTestBlock: (int (^)(int, int))block;
- (int) computeWithValue:(int)value addValue:(int)value2;
@end
#import "Test1.h"
@implementation Test1
@synthesize testBlock;
- (int) computeWithValue:(int)valueaddValue:(int)value2
{
if (testBlock == nil)
{
return 0;
}
return testBlock(value, value2);
}
@end
Test1 * example = [[Test1 alloc] init];
int a = 3;
[examplesetTestBlock:^int(int x, int y){
int sum;
sum = x + y;
return sum * a;
}];
NSLog(@"%d",[example computeWithValue:8 addValue:4]);
輸出為36
當某個Block通路了一個在該Block之前聲明的變量時,就可以說該Block捕獲了這個變量。
“捕獲變量”的要點:一旦某個Block對象捕獲了某個變量的值,那麼無論執行該Block對象多少次,被捕獲的值也不會發生改變。并且被捕獲的變量的值在Block之後修改,Block捕獲的變量的值還是之前的值。代碼如下:
int a = 3;
[example setTestBlock:^int(int x, int y){
int sum;
sum = x + y;
return sum * a;
}];
a= 6;
NSLog(@"%d",[example computeWithValue:8 addValue:4]);
輸出值為36
這兒簡單總結關于 Block Objects 變量的特點:
1. 局部變量在 Block Objects 和 Objective-C 方法中的工作原理非常相似。
2. 對于内聯Block Objects,局部變臉不僅包含Block内部定義的變量,并且包含在BlockObjects執行方法中定義的變量。
3. 你不能參考self;在Objective-C類中運作的獨立Block Objects,如果你需要通路self,就必須把Object作為參數傳遞到 BlockObject
4. 隻有當 self 出現在建立 Block Object 的詞法範圍内,你可以在内聯 Block Object 内參考 self。
5. 對于内聯Block Objects,那些在BlockObject執行過程中定義的局部變量是可讀寫的,換句話說,對于Block Objects 自身的局部變量來說,Block Objects 有個讀寫存取。
6. 對于内聯 Block Objects,實作 Object 的 Objective-C 方法的局部變量隻能從中讀取,不能寫入。不過還有一個例外,如果定義它們通過 __block 存儲類型定義的話,Block Object可以寫入此類的變量。對此我們也會有舉例。
7. 假設你有一個類NSObject的Object,并且在這個Object的執行中你使用了一個Block Object與GCD相連,那麼在這個 Block Object 内部,你會有一個存儲來讀取那個支援你的 Block 執行的 NSObject内部的聲明屬性。