標籤:
block
block用來儲存一段代碼
block的標誌:^
block跟函數很像:可以儲存代碼、有傳回值、有形參、調用方式跟調用方法一樣
block內部可以訪問外面的變數
預設情況下,block內部不能修改外面的局部變數
給局部變數加上__block關鍵字,這個局部變數就可以在block內部修改
利用typedef定義block類型
typedef int (^MyBlock)(int, int);
以後就可以利用MyBlock這種類型來定義block變數
MyBlock block;
MyBlock b1, b2;
沒有傳回值、沒有形參的blocs
有形參、有傳回值的block
以下是拷貝,借鑒的博文
二、記憶體位置(ARC情況)
1、block塊的儲存位置(block塊入口地址):可能存放在2個地方:代碼區、堆區(程式分5個區,還有常量區、全域區和棧區,對於MRC情況下代碼還可能存在棧區。關於分區詳細參考:http://www.cnblogs.com/mddblog/p/4405165.html
情況1:代碼區
不訪問處於棧區的變數(例如局部變數),且不訪問處於堆區的變數(例如alloc建立的對象)。也就是說訪問全域變數也可以。
/** 沒有訪問任何變數 */int main(int argc, char * argv[]) { void (^block)(void) = ^{ NSLog(@"==="); }; block();}
/** 訪問了全域(靜態)變數 */int iVar = 10;int main(int argc, char * argv[]) { void (^block)(void) = ^{ NSLog(@"===%d",iVar); }; block();}
情況2:堆區
如果訪問了處於棧區的變數(例如局部變數),或處於堆區的變數(例如alloc建立的對象)。都會存放在堆區。(實際是放在棧區,然後ARC情況下自動又拷貝到堆區)
/** 訪問局部變數 */int main(int argc, char * argv[]) { int iVar = 10; void (^block)(void) = ^{ NSLog(@"===%d",iVar); }; block();}
2、注意事項
代碼存放在堆區時,就需要特別注意,因為堆區不像代碼區不變化,堆區是不斷變化的(不斷建立銷毀)。因此代碼有可能會被銷毀(當沒有強指標指向時),如果這時再訪問此段代碼則會程式崩潰。因此,對於這種情況,我們在定義一個block屬性時應指定為strong,或copy:
@property (nonatomic, strong) void (^myBlock)(void); // 這樣就有強指標指向它
@property (nonatomic, copy) void (^myBlock)(void); // 並不會在堆區copy一份,原因見 三
而對於第1種情況(代碼存在代碼區),使用strong,copy(不會複製一份到堆區)也可以。因此定義block時最好指定為strong(推薦)或copy。
3、指定為copy後是否會拷貝一份呢?(或者說是淺拷貝還是深拷貝)
1 copy可變變數:在賦值指標的同時也會複製指標指向的記憶體地區。深拷貝,例如NSMutableString對象。
2 copy不可變變數:等同於strong,還是淺拷貝,例如NSString對象。
因為block是一段代碼,即不可變的,所以並不會深拷貝。
Objective-C( block的使用)