Block
Block的三种类型
根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock
- NSGlobalBlock:类似函数,位于数据区
- NSStackBlock:位于栈内存,函数返回后Block将无效
- NSMallocBlock:位于堆内存
全局block (
__NSGlobalBlock__),定义在函数外面的block是global的;另外如果函数内部的 block,但是没有捕获任何自动变量,那么它也是全局的(ARC和MRC都一样)堆block 则是对栈block copy 得来。对全局block copy 不会有任何作用,返回的依然是全局block。 在ARC下,只要在block内部引用外部变量,此时这个block是一个堆block,而在MRC下是栈block
总结:
ARC 下
- 没有使用外部变量
NSGlobalBlock - 使用外部变量
堆block
- 没有使用外部变量
MRC 下
- 没有使用外部变量
NSGlobalBlock - 使用外部变量
栈block
- 没有使用外部变量
- 对一个栈block 通过copy可以得到堆block
block类型变量内存管理参数为什么要使用 copy
- 不管再MRC还是在ARC,使用assign 修饰的block,都是栈block
- 如果block变量内存管理参数适用assign,此时变量是栈block,栈block会被提前释放,导致无法继续使用,会造成
EXC_BAD_ACESS错误
block本质
block对象就是一个结构体,里面有isa指针指向自己的类(global malloc stack),有desc结构体描述block的信息,forwarding指向自己或堆上自己的地址,如果block对象截获变量,这些变量也会出现在block结构体中。最重要的block结构体有一个函数指针,指向block代码块。block结构体的构造函数的参数,包括函数指针,描述block的结构体,自动截获的变量(全局变量不用截获),引用到的block变量。(__block对象也会转变成结构体)
block代码块在编译的时候会生成一个函数,函数第一个参数是前面说到的block对象结构体指针。执行block,相当于执行block里面__forwarding里面的函数指针