美文网首页
09.block全解析(1):它的本质和捕获情况

09.block全解析(1):它的本质和捕获情况

作者: 白开了杯水 | 来源:发表于2021-08-30 15:42 被阅读0次

    涉及知识章节:
    01.OC实例对象的本质

    block本质就是一个对象

    它封装了函数调用,我们可以通过编译后的源码来瞧一瞧,如下图:

    block的简单使用main函数 编译后的main函数代码 block结构体__main_block_impl_0 __main_block_impl_0的成员__block_impl

    可以看到,编译后block的结构体包含了block_impl,而block_impl跟NSObject一样也拥有isa等成员变量,侧面证明了它是一个对象,具体的代码解析看图片里的代码注释,另外,既然是对象,那我们尝试调用class方法,来打印block的类型,如以下代码,也确实证明了它是一个对象

    block的class方法调用 block本质结构图

    接下来将举例各种情形下的block编译后源码,首先上面的那一种是无参block,第二种是带参数带返回值的block,看看源码如图:

    带参数带返回值的block调用 编译后的block代码

    可以看到,修改了block,只会修改block里面函数的定义,则编译器会自动根据定义的block封装对应的函数

    除了函数定义,block往往会用到外面的变量,而变量的定义可以分为三种:

    • auto普通变量
    • static静态变量
    • 全局变量

    那么这三种变量的捕获有事怎样子的呢?让我们来瞧瞧,首先是普通变量,如以下代码:

    auto普通变量捕获调用 auto普通变量编译后源码block结构

    可以看到,它直接在block结构体中声明了age的成员,然后在构造方法中传入,由于普通变量是在栈孔健,所以这里会直接对age进行复制操作,也就是里面的age和外面的age已经无关,是俩个age变量,如下图俩个地址对比

    结果输出地址和值

    那么接下来看看static修饰的age是怎样的

    static变量捕获调用 static变量捕获的block结构代码

    从上图可以看出,static修饰的变量,直接变成指针变量,指向了age同一块内存,所以修改了age的值,那么block里面的age也会同步改变
    最后还有一个全局变量是如何的呢?看图:

    全局变量block的捕获调用

    可以看到输出结果与static一致,但static修饰是有被捕获的,那全局变量是否会捕获?看看源码:

    全局变量block的结构代码

    证明了一个事实,全局变量不会被捕获!

    总结
    • 局部变量会被捕获,auto捕获的是值,static捕获的是地址
    • 全局变量不会被捕获,直接使用
    捕获总结图
    tips

    编译后的源码使用该命令

    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main1.cpp
    

    下一章将讲解block的类型

    相关文章

      网友评论

          本文标题:09.block全解析(1):它的本质和捕获情况

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