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