block内部为什么不能够直接修改 auto 变量的值?
因为 auto age 变量是在栈上存放的, 当函数作用域结束时就会被销毁,而 block 执行的函数是在另一个函数方法里, 这个函数是无法访问到 auto age 变量的 ,虽然 block内部也会生成一个一模一样的变量 age 但是这个 age变量 是 block 内部的 不会影响到外部的 auto 变量 age . 因此 block 内部是无法去修改
怎么样才能在 block 内部去修改局部变量的值呢 ?
有两种方法可以修改到 变量 age 的值 ,第一种 用static 修饰 age 变量 ,由于是静态变量 它会存放在一个 .data区 这块的内存是随着应用的生命周期而结束,这样就造成了 age 这个变量 无法被释放掉
第二种方法 就是用 __block 去修饰 age 变量,即不改变 age 是 auto 类型的变量 又可以在 block 内部去修改 age 的值 .
__block是怎么实现对局部变量的修改呢?
带着这个问题 我们将这段代码转成C++的代码 一窥究竟
void testBlock() {
去掉一些强制类型转换后 简化为下边的代码
MyBlock block;
__Block_byref_age_0 age = {0,&age, 0, sizeof(__Block_byref_age_0), 10};
block = &__testBlock_block_impl_0(__testBlock_block_func_0, &__testBlock_block_desc_0_DATA,&age, 570425344));
block->FuncPtr)(block);
}
///Block 内部结构 不再是 int age 而是 __Block_byref_age_0 *age
struct __testBlock_block_impl_0 {
struct __block_impl impl;
struct __testBlock_block_desc_0* Desc;
__Block_byref_age_0 *age; // by ref
__testBlock_block_impl_0(void *fp, struct __testBlock_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;
}
};
__Block_byref_age_0 其实也是一个OC对象 内部有 isa 指针
struct __Block_byref_age_0 {
void *__isa; ///表示它是一个OC对象
__Block_byref_age_0 *__forwarding; ///一个指向自身的结构体指针
int __flags;
int __size; ///内存大小
int age; ///外部 auto 变量age的值
};
__Block_byref_age_0 age = {0,&age, 0, sizeof(__Block_byref_age_0), 10};
同过 block 内部的 age -> __forwarding指针 -> age 去修改 age 的值
static void __testBlock_block_func_0(struct __testBlock_block_impl_0 *__cself) {
__Block_byref_age_0 *age = __cself->age; // bound by ref
///同过 block 内部的 age -> __forwarding指针 -> age 去修改 age 的值
(age->__forwarding->age) = 20;
NSLog((NSString *)&__NSConstantStringImpl__var_folders_hj_pwgsq9614nb0vq4zd315tcx80000gn_T_main_163d3b_mi_0,(age->__forwarding->age));
}