一、截获自动变量值
//截获自动变量值 int val = 132; const char *fmt = "val = %d\n"; /* 在blocks中,block表达式使用的是在它声明之前的自动变量val。 block表达式截获所使用的自动变量的值,即保存了该自动变量的瞬间值, 因为block表达式保存了自动变量的值,所以在执行block语法后,即使改变bock中使用的自动变量的值也不会影响block执行时自动变量的值 所以两次输出的结果是一样的 都是:val = 132 */ void (^blk)(void) = ^{ printf(fmt,val); }; blk(); val = 12345; blk();
二、__block 说明符
//__block说明符 /* 实际上,自动变量值截获只能保存在执行block语法瞬间的值,保存后就不能改写该值。 如果在block中尝试改变截获的自动变量的值,看看会有什么结果 */ int val = 0; void (^blk)(void) = ^{ val = 1; }; blk();
这个时候就会出现如下图的错误提示啦:
那么该如何解决呢?-------- 使用 __block 说明符
//若想在block语法的表达式中将值赋给在block语法外声明的自动变量, //需要在该自动变量的前面附加 __block 说明符,就可以实现在block内赋值。 __block int val = 0; void (^blk)(void) = ^{ val = 1; NSLog(@"val = %d",val); }; blk();
上面提到,如果将值赋给block中的自动变量,就会产生编译错误。那么对于截获的objective-c对象,调用变更该对象的方法也会产生这样的编译错误吗?
请看下面的例子:
id array = [[NSMutableArray alloc]init]; void (^blk)() = ^{ id obj = [[NSObject alloc] init]; [array addObject:obj]; }; blk();
id array = [[NSMutableArray alloc]init]; void (^blk)() = ^{ array = [[NSMutableArray alloc]init]; }; blk();
显然,需要给截获的自动变量附加 __block 说明符才可以解决问题。
四、另外,在使用c语言数组的时候必须小心使用其指针,例如:
const char text[] = "hello world"; void (^blk)(void) = ^{ printf("%c \n",text[2]); };
其实在block中,截获自动变量的方法并没有实现对c语言数组的截获,这时可以使用指针解决这个问题。
上面的代码稍微改动一下就可以了。
const char *text = "hello world"; void (^blk)(void) = ^{ printf("%c \n",text[2]); }; blk();
五、
Block会保持一个strong指针指向block内被使用的所有对象,即这些被引用的对象会保持在heap中直到block生命周期结束。
MemoryCycle(内存循环)问题:
以下(在控制器类中)定义属性并使用Block 的代码:
@property(nonatomic ,strong) NSMutableArray *myBlocks;// block array
[self.myBlocksaddObject:^{ //Block可当作对象使用
[selfdoSomething];
}];
由于 Block 内引用了 self,因此self(通过myBlocks 属性) 和 Block 均有 一个strong 指针指向彼此,此时self 及 Block 均无法从内存中释放!
解决方法:
定义一个 weak 指针:
__weakMyClass *weakObj = self;
//arrayofblocks
@property(nonatomic,strong)NSArray*myBlocks;
[self.myBlocks addObject:^{
[weakObjdoSomething];
}];
Block拥有一个指向weakObj 的 weak 指针,self 拥有一个指向 myBlock 的 strong 指针。