1,block 在实现时就会对它引用到的它所在方法中定义的栈变量进行一次只读拷贝,然后在 block 块内使用该只读拷贝。
如下代码:
- - (void)testAccessVariable
- {
- NSInteger outsideVariable = 10;
- //__block NSInteger outsideVariable = 10;
- NSMutableArray * outsideArray = [[NSMutableArray alloc] init];
- void (^blockObject)(void) = ^(void){
- NSInteger insideVariable = 20;
- KSLog(@" > member variable = %d", self.memberVariable);
- KSLog(@" > outside variable = %d", outsideVariable);
- KSLog(@" > inside variable = %d", insideVariable);
- [outsideArray addObject:@"AddedInsideBlock"];
- };
- outsideVariable = 30;
- self.memberVariable = 30;
- blockObject();
- KSLog(@" > %d items in outsideArray", [outsideArray count]);
- }
输出结果为:
- > member variable = 30
- > outside variable = 10
- > inside variable = 20
- > 1 items in outsideArray
注意到没?outside 变量的输出值为10,虽然outside变量在定义 block 之后在定义 block 所在的方法 testAccessVariable 中被修改为 20 了。这里的规则就是:blockObject 在实现时会对 outside 变量进行只读拷贝,在 block 块内使用该只读拷贝。因此这里输出的是拷贝时的变量值 10。如果,我们想要让 blockObject 修改或同步使用 outside 变量就需要用 __block 来修饰 outside 变量。
__block NSInteger outsideVariable = 10;
注意:
a),在上面的 block 中,我们往 outsideArray 数组中添加了值,但并未修改 outsideArray 自身,这是允许的,因为拷贝的是 outsideArray 自身。
b),对于 static 变量,全局变量,在 block 中是有读写权限的,因为在 block 的内部实现中,拷贝的是指向这些变量的指针。
c), __block 变量的内部实现要复杂许多,__block 变量其实是一个结构体对象,拷贝的是指向该结构体对象的指针。