初探iOS中的Block(程式碼塊與閉包)
支援原創,轉載請註明博主與博文連結,3Q
—— by atany
一、Block是什麼?
Block就是一個包含函式體的物件,有時候也被叫做閉包。
概念可能還是有點模糊,沒關係,我們來看看用法。
二、Block的宣告與建立。
程式碼塊的基本結構為:
returnType (^blockname)(list of arguments) =^(arguments){ body; }
舉個例子:我們定義一個作用為打出“Hello + 名字”的閉包。
void(^sayHelloBlock)(NSString*) = ^(NSString *personName){ NSLog (@"Hello %@", personName); };
對應的拆解:
void:返回值.
^sayHelloBlock:[^]符號宣告block物件,“sayHelloBlock”為blockname。
(NSString*):block的輸入引數列表。(也可以寫成NSString *personName的完整形式)
(NSString *personName):詳細引數,必須寫完整形式,變數personName會在block中用到。
{ NSLog (@"Hello %@", personName);};:body,也就是block的內容,這裡是打印出一句話。
宣告與建立完成後,我們來看看Block的使用:block的使用與函式十分相似,直接使用(block名稱+引數)的形式。
sayHelloBlock(@"atany");
打印出:2013-09-1120:18:54.130 TestBlock[3137:c07] Hello atany
三、Block的特性
1) Block可以訪問函式其他的內部變數
NSString *person = @"Mary";
void(^sayHelloBlock)()= ^{
NSLog(@"Hello %@",person);
};
sayHelloBlock();
輸出:2013-09-11 20:26:06.050TestBlock[3176:c07] Hello Mary
可以看到person物件在Block的外部,但是Block卻能夠訪問到person物件的值Mary,這也是block最重要的一個特性。
2) Block宣告時會捕捉建立點的狀態。
NSString *person = @"Mary";
void(^sayHelloBlock)()= ^{
NSLog(@"Hello %@",person);
};
sayHelloBlock ();
person = @"Peter";
sayHelloBlock();
輸出:
2013-09-11 20:28:38.423 TestBlock[3200:c07] Hello Mary
2013-09-11 20:28:38.424TestBlock[3200:c07] Hello Mary
為什麼會這樣呢?怎麼沒有打出Hello Peter?
原來當程式執行到Block的宣告時,Block會記錄建立點所用資源的狀態,此時person的值為“Mary”,Block儲存這個值的副本,再次使用時直接呼叫副本。所以即使在後面person的值變為了“Peter”,副本的值也不會改變。
那怎麼辦呢?有兩種解決方法。
1) 修改物件為靜態.
static NSString *person= @"Mary";
2) 在物件宣告前新增__block.
__block NSString *person = @"Mary";
輸出:
2013-09-11 20:35:29.838TestBlock[3244:c07] Hello Mary
2013-09-1120:35:29.840 TestBlock[3244:c07] Hello Peter
可以看到,兩個方法都可以解決問題。