block的底层实现

1、我们都会使用 block ,但是它真正是如何工作的呢?换句话说block的本质是什么?
看下列实例,想想程序的结果:

int main(int argc, const char * argv[]) {
     int a = 10;
    __block int b = 20;
     void (^block)() = ^(){

         printf("a = %d\n",a);

         printf("b = %d\n",b);

     };
    a = 50;
    b = 30;

    block();

程序的结果是: a = 10 , b = 30;

这个结果可能大家都知道 ,那么为什么会出现这样的情况呢?很多人都会说 ,b前面加了__block所以他的值可以改变 ,a没加所以不能改变 。这只是表象,接下来我们就研究一下他的block的本质。

2、探究block的底层原理,打开终端 ,把目录切换到当前main.m所在的路径下,我们需要把这个 main.m 文件 编程成c++ 的文件 main.cpp.
输入终端命令: clang -rewrite-objc main.m
生成一个main.cpp文件 ,打开它,但是你要做好心理准备,这个 文件十万多行。

3、找到下列代码

int main(int argc, const char * argv[]) {

     int a = 10;
    //__attribute__((__blocks__(byref))) __Block_byref_b_0 b = {(void*)0,(__Block_byref_b_0 *)&b, 0, sizeof(__Block_byref_b_0), 20};
     void (*block)() = &__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a, (__Block_byref_b_0 *)&b, 570425344);
    a = 50;
    (b.__forwarding->b) = 30;

    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

    return 0;
}}

分析:
3.1、分析这个block参数
&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a, &b, 570425344)

//block -> 实质 函数指针
//__main_block_func_0 指针
//__main_block_desc_0_DATA 地址 block 的描述数据
//a 普通变量
//&b b地址 b -> __Block_byref_b_0类型
//b 变量 就会被封装成 __Block_byref_b_0 结构体类型

3.2、分析struct __Block_byref_b_0 结构体

 struct __Block_byref_b_0 {
        void *__isa;  //当前对象的指针
        __Block_byref_b_0 *__forwarding; //当前这种结构体类型的指针 __forwarding存对象自己地址
        int __flags; //标记
        int __size; //结构体的大小
        int b; //变量
    };

3.3、函数的初始化

 struct __main_block_impl_0 {
        struct __block_impl impl;
        struct __main_block_desc_0* Desc;
        int a; //  10
        __Block_byref_b_0 *b; // by ref
        __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, __Block_byref_b_0 *_b, int flags=0) : a(_a), b(_b->__forwarding) {
            impl.isa = &_NSConcreteStackBlock;
            impl.Flags = flags;
            impl.FuncPtr = fp;  //执行的那段代码 打印
            Desc = desc;
        }
    }

3.4、__block_impl结构体分析

 struct __block_impl {
        void *isa;
        int Flags;
        int Reserved;
        void *FuncPtr;
    };

3.5、__main_block_func_0

 __main_block_func_0(struct __main_block_impl_0 *__cself) {

        //地址 直接访问属性
        __Block_byref_b_0 *b = __cself->b; // bound by ref
        int a = __cself->a; // bound by copy

        printf("a = %d\n",a);

        printf("b = %d\n",(b->__forwarding->b));

    }

在上述的代码中我们可以理解为: 变量a传入的是值,变量b传入的是地址。__block 把b强转成一个结构体指针。

blcok的本质就是一个函数指针 ,也可以说是一个指向结构体的指针。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值