1.__block
- 我们知道堆上的block会捕获auto变量的值,会捕获静态变量和全局变量的指针.下面我们来看下被__block修饰的变量产生了那些变化
__block int age = 10;
void(^block)(void) = ^{
NSLog(@"%d",age);
};
block();
我们转一下c++
__attribute__((__blocks__(byref))) __Block_byref_age_0 age = {(void*)0,(__Block_byref_age_0 *)&age, 0, sizeof(__Block_byref_age_0), 10};
void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_age_0 *)&age, 570425344));
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
优化一下,去掉一些强制转换
__Block_byref_age_0 age = {
0,
&age,
0,
sizeof(__Block_byref_age_0),
10
};
*block = &__main_block_impl_0(main_block_func_0, &__main_block_desc_0_DATA, &age, 570425344);
block->FuncPtr();
- 当变量被__block修饰后,会被包装成__Block_byref_age_0的结构体
struct __Block_byref_age_0 {
void *__isa;
__Block_byref_age_0 *__forwarding;
int __flags;
int __size;
int age;
};
结构体又5个成员,上面就是对结构体赋值
block
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__Block_byref_age_0 *age; // by ref 这就是被block修饰的age变量
__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;
}
};
当访问age变量时其实是拿的__Block_byref_age_0 *age;所以被__block修饰的变量可以在block内部修改值.
网友评论