美文网首页将来跳槽用2019IV
__block修饰基本数据类型

__block修饰基本数据类型

作者: 大兵布莱恩特 | 来源:发表于2019-02-22 14:58 被阅读3次

    block内部为什么不能够直接修改 auto 变量的值?

    image.png

    因为 auto age 变量是在栈上存放的, 当函数作用域结束时就会被销毁,而 block 执行的函数是在另一个函数方法里, 这个函数是无法访问到 auto age 变量的 ,虽然 block内部也会生成一个一模一样的变量 age 但是这个 age变量 是 block 内部的 不会影响到外部的 auto 变量 age . 因此 block 内部是无法去修改

    怎么样才能在 block 内部去修改局部变量的值呢 ?

    有两种方法可以修改到 变量 age 的值 ,第一种 用static 修饰 age 变量 ,由于是静态变量 它会存放在一个 .data区 这块的内存是随着应用的生命周期而结束,这样就造成了 age 这个变量 无法被释放掉
    第二种方法 就是用 __block 去修饰 age 变量,即不改变 age 是 auto 类型的变量 又可以在 block 内部去修改 age 的值 .

    image.png

    __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));
     }
    
    

    好了,我是大兵布莱恩特,欢迎加入博主技术交流群,iOS 开发交流群

    QQ20180712-0.png

    相关文章

      网友评论

        本文标题:__block修饰基本数据类型

        本文链接:https://www.haomeiwen.com/subject/nlkeyqtx.html