不同类型变量的捕获方式
1、局部变量和block
使用局部变量的block
int main(int argc, const char * argv[]) {@autoreleasepool {int age = 10;block = ^{// age的值捕获进来(capture)NSLog(@"age is %d, ", age);};age = 20;block();}return 0;
}
clang编译后的底层代码
struct __test_block_impl_0 {struct __block_impl impl;struct __test_block_desc_0* Desc;int age;__test_block_impl_0(void *fp, struct __test_block_desc_0 *desc, int _age, int flags=0) : age(_age) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};
可以看到,在block的内部多了成员变量_age,并且在构造这个block时,会把age的值直接传进去,几_age=age,可以看出来这时是block捕获了局部变量,并且进行了值传递。
2、静态局部变量
int main(int argc, const char * argv[]) {@autoreleasepool {// auto:自动变量,离开作用域就销毁auto int age = 10;static int height = 10;void (^block)(void) = ^{// age的值捕获进来(capture)NSLog(@"age is %d, height is %d", age, height); // 10 20};age = 20;height = 20;block();}return 0;
}
编译后的结果:
struct __test_block_impl_0 {struct __block_impl impl;struct __test_block_desc_0* Desc;int age;int *height;__test_block_impl_0(void *fp, struct __test_block_desc_0 *desc, int _age, int *_height, int flags=0) : age(_age), height(_height) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};//定义的时候
block = ((void (*)())&__test_block_impl_0((void *)__test_block_func_0, &__test_block_desc_0_DATA, age, &height));
//执行的时候
static void __test_block_func_0(struct __test_block_impl_0 *__cself) {int age = __cself->age; // bound by copyint *height = __cself->height; // bound by copyNSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_d2875b_mi_0, age, (*height));}
可以看出来age传递的是值,但是静态局部变量height传递的是指针。
3、全局变量和block
int age_ = 10;
static int height_ = 10;
void (^block)(void);
int main(int argc, const char * argv[]) {@autoreleasepool {void (^block)(void) = ^{NSLog(@"age is %d, height is %d", age_, height_);};age_ = 20;height_ = 20;block();}return 0;
}
编译后:
struct __main_block_impl_0 {struct __block_impl impl;struct __main_block_desc_0* Desc;// 构造函数(类似于OC的init方法),返回结构体对象__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {impl.isa = &_NSConcreteStackBlock;impl.Flags = flags;impl.FuncPtr = fp;Desc = desc;}
};
//调用函数的时候
static void __test_block_func_0(struct __test_block_impl_0 *__cself) {NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_d2875b_mi_0, age_, height_);}
可以看到全局变量没有捕获到block内部,是直接访问的,所以每次访问都能获得最新值。