欢迎查看block连载博客:
【block编程第一篇】block语法
【block编程第二篇】block捕获变量和对象(当前)
【block编程第三篇】block的内存管理。
【block编程第四篇】block内部实现;
【block编程第五篇】block中如何避免循环引用
------------------------------------------------------------------------------------------------------------------------------
下面介绍,block捕获自动变量和对象
int val = 10;
void (^blk)(void) = ^{printf("val=%d\n",val);};
val = 2;
blk();
上面这段代码,输出值是:val = 10.而不是2.
block 在实现时就会对它引用到的它所在方法中定义的栈变量进行一次只读拷贝,然后在 block 块内使用该只读拷贝;换句话说block截获自动变量的瞬时值;或者block捕获的是自动变量的副本。(我更喜欢这么理解:block捕获变量的机制更像是函数按值传递。)
由于block捕获了自动变量的瞬时值,所以在执行block语法后,即使改写block中使用的自动变量的值也不会影响block执行时自动变量的值。深入了解block是如何实现捕获变量的,点击查看【block四篇】block的实现
__block int val = 10;
void (^blk)(void) = ^{printf("val=%d\n",val);};
val = 2;
blk();上面的代码,跟第一个代码段相比。只是多了一个__block修饰符。但是输出结果确是2了。@interface MyClass : NSObject {
NSObject* _instanceObj;
}
@end
@implementation MyClass
NSObject* __globalObj = nil;
- (id) init {
if (self = [super init]) {
_instanceObj = [[NSObject alloc] init];
}
return self;
}
- (void) test {
static NSObject* __staticObj = nil;
__globalObj = [[NSObject alloc] init];
__staticObj = [[NSObject alloc] init];
NSObject* localObj = [[NSObject alloc] init];
__block NSObject* blockObj = [[NSObject alloc] init];
typedef void (^MyBlock)(void) ;
MyBlock aBlock = ^{
NSLog(@"%@", __globalObj);
NSLog(@"%@", __staticObj);
NSLog(@"%@", _instanceObj);
NSLog(@"%@", localObj);
NSLog(@"%@", blockObj);
};
aBlock = [[aBlock copy] autorelease];
aBlock();
NSLog(@"%d", [__globalObj retainCount]);
NSLog(@"%d", [__staticObj retainCount]);
NSLog(@"%d", [_instanceObj retainCount]);
NSLog(@"%d", [localObj retainCount]);
NSLog(@"%d", [blockObj retainCount]);
}
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
MyClass* obj = [[[MyClass alloc] init] autorelease];
[obj test];
return 0;
}
}执行结果为1 1 1 2 1。
热门源码