如何在block内部修改外部变量?
int age = 10;
void (^block)(void) = ^{
age = 20;
};
block();
如上代码,编译会报错,因为age变量会被捕获,因为是auto变量,所以是值传递..如果想修改age变量,办法如下:
- 1.修改
age
为全局变量(永久占用内存) - 2.使用
static
修饰age(永久占用内存) - 3.在外部使用
__block
修饰变量(仍然是auto变量)
__block
转成C++后查看源码
struct __Block_byref_age_0 {
void *__isa;
__Block_byref_age_0 *__forwarding;
int __flags;
int __size;
int age;// 10
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_age_0 *age; // by ref
// 构造函数
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_age_0 *_age, int flags=0) : age(_age->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
凡是有isa都认为是Objective-C对象
可以看到生成的block内部多了一个成员变量,在构造函数里面使用了_age->__forwarding
初始化这个变量,这个变量就是一个__Block_byref_age_0
结构体,而这个结构体内部有age成员变量,这个__forwarding
指向的就是这个__Block_byref_age_0
结构体它自己;
查看age这个auto变量的修改源码
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
__Block_byref_age_0 *age = __cself->age; // bound by ref
(age->__forwarding->age) = 20;
}
编译器会将__block
变量包装成一个对象
__block
可以用于解决block内部无法修改auto变量值的问题
__block
不能修饰全局变量、静态变量(static)