Block:带有自动变量的匿名函数。
匿名函数:没有函数名的函数,一对{}包裹的内容是匿名函数的作用域。
自动变量:栈上声明的一个变量不是静态变量和全局变量,是不可以在这个栈内声明的匿名函数中使用的,但在Block中却可以。
准备Demo
1 |
|
将ViewController.m编译成C++,以便研究,脚本命令如下:
1 | clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk ViewController.m |
下面来逐一进行分析
block0
编译器生成的结构与实现
调用
block最终被还原成了一个结构体,成员:实现(imp)和描述(Desc)
block的调用事实上是调用结构体img的函数指针,并将结构体本身做为参数传入
imp
isa指向_NSConcreteStackBlock类
FuncPtr指向函数指针,参数是结构体指向自己的指针
Desc
存储结构体的大小
block1
与block0唯一的区别就在于多了一个传入的参数NSString
block2
相信读者也有发现,以上的常见block写法都imp的isa都是指向_NSConcreteStackBlock类。其实还会指向另一种类——_NSConcreteGlobalBlock,这种场景比较特殊,在全局里声明的block才会去指向这个类。
block_global
global block也有上面三种形态,在这里就不一一展示了。