網上有很多block文章,這篇只用來記錄自己認為重要的點。
一、block本質是個對象,涉及閉包的概念,用於封裝代碼
int (^block)(int a,int b) = ^(int a,int b){ return a + b; };
定義: int (^block)(int a,int b)
參數: int 返回類型
int a 輸出參數a(名稱可以不寫)
int b 輸入參數b(名稱可以不寫)
實現:^(int a,int b){ return a + b; };
參數:int a,int b (名稱不可缺)
{}實現
二、block由儲存位置不同有的類型,這些類型只有編譯器使用
1、 _NSConcreteStackBlock (NSStackBlock) 存儲在棧上;
2、 _NSConcreteGlobalBlock (NSGlobalBlock) 存儲在程序的代碼段;
3、 _NSConcreteMallocBlock (NSMallocBlock) 存儲在堆上。
知識提示:C語言中儲存有程序代碼區(text)、全局區(靜態)、常量區、棧區(stack)、堆區(heap,使用malloc)
說明:
- NSGlobalBlock:在block內部沒有引用任何外部變量
- NSStackBlock:在block內部引用外部變量,處於棧上的block會隨棧退出,引用導致奔潰。
- NSMallocBlock:在其作用域外部使用的指針增加(copy、rerain)
注意:在arc情況下,沒有NSStackBlock這個類型,如果有系統自動copy成為NSMallocBlock,同時拷貝代碼內部變量如:
int base = 2;
base += 2; // base->4
long (^sums)(int,int) = ^ long (int a,int b){
return base + a + b; //base->4
};
base ++; //base->5
NSLog(@"%ld",sums(1,2));
//輸出的結果為 7 arc下提前拷貝base
經典事例,自帶答案:http://blog.parse.com/learn/engineering/objective-c-blocks-quiz/
三、引用問題:只有NSMallocBlock支持retain、release操作 (老生常談了具體自己搜吧)
1、block 內部代碼修改數據情況:__block修飾、static
2、循環引用的問題:block代碼段強引用,使用 __weak typeof (self) weakSelf = self;
3、block對象被提前釋放:不要用__block