內(nèi)存管理篇之Blocks
Blocks 是 C 語言的擴充功能:帶有自動變量(局部變量)的匿名函數(shù)
1. Block 類型變量
聲明如下:
int (^block)(int);
block 實現(xiàn)賦值
int(^block)(int) = ^(int num) {
NSLog(@"%d",num);
return num + 10;
};
block(222);
可以按照如下格式定義一個類型:typedef returnType(^blockName)(parameterType) ;
2. Block 作為函數(shù)參數(shù)
格式1:- type funckName:(returnType(^)(parameterType)) blockName{}
//定義類型
typedef void(^myblock)(int) ;
//聲明屬性--可以直接把 block 名當(dāng)做一個類型使用
@property (nonatomic, copy) myblock block;
//block 作為函數(shù)參數(shù)方式一
-(void)blockTest:(void(^) (int)) func{
func(2);
}
//block 作為函數(shù)參數(shù)方式二
-(void)blockTest2:(myblock ) func{
func(2);
}
3. Block 截獲局部變量值
block 截獲的是 自動變量的瞬間值.也就是說在 block 定義之后改變了 自動變量值,也不會影響 block 執(zhí)行時候的值了
NSString* str = @"test";
void (^pBlock)(void) = ^{
NSLog(@"str = %@",str);
};
str = @"test2";
pBlock();
打印結(jié)果: str = test
4. __block說明符
block 因為截獲的只是 變量的瞬間值,因此是不能修改的.如果嘗試修改會報編譯錯誤. 如果想在 block 中修改外部變量的值,需要在外部使用__ block 說明符.
這個會報編譯錯誤:
NSString* str = @"test";
void (^pBlock)(void) = ^{
NSLog(@"str = %@",str);
str = @"change test";
};
下面的正常:
__block NSString* str = @"test";
void (^pBlock)(void) = ^{
NSLog(@"str = %@",str);
str = @"change test";
};
5. 截獲自動變量
如果 向 block 中截獲的自動變量賦值,就會產(chǎn)生編譯錯誤,基本數(shù)據(jù)類型和 OC 類型都一樣,但是調(diào)用 OC 對象的方法不會產(chǎn)生編譯錯誤
下面的代碼運行正常:
NSMutableArray *arr = [NSMutableArray array];
void (^pBlock)(void) = ^{
[arr addObject:@"test"];
};
pBlock();
下面的代碼嘗試給 arr賦值,編譯異常:
NSMutableArray *arr = [NSMutableArray array];
// __block NSMutableArray *arr = [NSMutableArray array]; //這樣會沒有異常
void (^pBlock)(void) = ^{
arr = [NSMutableArray array];
};
pBlock();
6. 允許 block 改寫截獲的自動變量的幾種情況
- __block說明符修飾
- 靜態(tài)變量
- 靜態(tài)全局變量
- 全局變量
如下面幾個例子
int globleParam = 1; //1>全局變量
static int sGlobleParam = 2; //2>靜態(tài)全局變量
int main(int argc, char * argv[]) {
static int index = 3; //3>靜態(tài)局部變量
// __block int index = 4; //4>__block 說明符
void (^pBlock)(void) = ^{
globleParam *= 2;
sGlobleParam *= 2;
index = 2;
};
pBlock();