__block

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内部修改值.

猜你喜欢

转载自blog.csdn.net/weixin_33968104/article/details/87813564