Block 底层值__Block修饰符

__Block 修饰符

Block 想要改变外部的变量,必须要用__Block 来修饰自动变量。

根据内存地址可以看出来,__block 所修饰的变量,将外部的变量在栈中的内存地址放到了堆中。

        // auto 自动变量的内存分配在栈区域 stack
        __block int meters = 1000;
        // 在block 引用之前 0x7ffeefbff4f8
        NSLog(@"在block 引用之前 %p",&meters);
        // 3 无返回值无参数
        void (^Run1)(void) = ^{
            
            meters = 2000;
            // 在block 引用之后 0x100502ac8
            NSLog(@"在block 引用之后 %p",&meters);
            NSLog(@"i have run %d meters",meters);
        } ;
        
        Run1();

转为C++ 代码 看出

meter 是如何改变的

先是找到 __forwarding 结构体,然后的话再去找打结构体内部的meter 属性

(meters->__forwarding->meters) = 2000;

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_meters_0 *meters; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_meters_0 *_meters, int flags=0) : meters(_meters->__forwarding) {
    
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

// meter 包装成一个对象,里面是含有一个isa 指针的
struct __Block_byref_meters_0 {
  void *__isa;
__Block_byref_meters_0 *__forwarding;
 int __flags;
 int __size;
 int meters;
};

//meter 是如何改变的

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_meters_0 *meters = __cself->meters; // bound by ref
    
            (meters->__forwarding->meters) = 2000;
        }


  • 1 在ARC 环境下,Block 被引用的时候,会被Copy 一次,由栈区Copy 到堆区域

  • 2 在Block 被Copy的时候,Block 内部的变量也会被copy 一份到堆上面

  • 3 被__Block 修饰的变量,在被Block 引用的时候,会变成结构体也就是OC的对象,里面的————forwarding 指针由栈copy 到堆上面

  • 4 栈上__block 变量结构体中,__forwarding的指针指向堆上面__block 变量结构体,堆上的__block 变量结构体中的

    __forwarding 指针指向自己

  • 5 当block 从堆中移除的时候,会调用block 内部的dispose 函数,dispose函数内部会调用_Block_object_dispose函数,_Block_object_dispose函数会自动释放引用的__block变量(release)

图片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值