涉及知识章节:
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也会同步改变
最后还有一个全局变量是如何的呢?看图:
可以看到输出结果与static一致,但static修饰是有被捕获的,那全局变量是否会捕获?看看源码:
全局变量block的结构代码证明了一个事实,全局变量不会被捕获!
总结
- 局部变量会被捕获,auto捕获的是值,static捕获的是地址
- 全局变量不会被捕获,直接使用
tips
编译后的源码使用该命令
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main1.cpp
下一章将讲解block的类型
网友评论