基础知识 - BLOCK

什么是block
将函数及其可执行上下文封装起来的对象(isa指针)
block本质
通过clang可以查看源码实现
函数调用
本质是一个对象
block类型(MRC)
全局block NSGlobalBlock 未访问外部变量或者只访问了静态变量(包括全局静态变量和局部静态变量)和全局变量
栈block NSStackBlock 访问局部变量
堆block NSMallocBlock __NSStackBlock__调用了copy
block类型(ARC)
全局block NSGlobalBlock 未访问外部变量或者只访问了静态变量(包括全局静态变量和局部静态变量)和全局变量
堆block NSStackBlock 访问局部变量
block类型总结
MRC环境下,不访问外部变量或者只访问静态变量或者全局变量的为全局block,只访问局部变量(不包含静态变量)的为栈block,栈block执行copy操作会变成堆block,ARC状态下会自动把栈block copy到堆上,所以arc状态下么有栈block
block截获变量
局部变量
- 基本数据类型 截获其值
- 对象类型 截获其值 连同该对象所有权修饰符一起截获
- 静态局部变量 指针截获
全局变量 - 静态全局变量 不截获
- 全局变量 不截获
__block修饰符
局部变量
- 基本数据类型 需要__block
- 对象类型 需要__block
- 静态局部变量 不需要__block
全局变量 - 静态全局变量 不需要__block
- 全局变量 不需要__block
对被截获变量发生赋值操作,需要用到__block修饰符
__block修饰的变量最终变成了对象
使用 和 赋值 的理解
__block会把变量变成一个拥有isa指针和forwarding指针的对象,forwarding对象指向对象本身,通过forwarding去修改变量值
block内存管理
block发生赋值操作时会执行copy,栈block在内存中的地址copy一份到堆中,这样,栈中block作用域结束后,栈block就会释放掉,而堆block由于在堆中,当堆中block作用域结束后,会在最近一次autoreleasepool执行结束释放掉
__block来修饰变量
__block修饰变量,会把变量变成一个对象,该对象有它自己的isa指针和forwarding指针,forwarding指向该对象本身,当block发生copy操作后,同样会把__block修饰的变量也copy一份在堆中,此时原对象的forwarding指向堆中block中的变量,堆中变量forwarding指针指向变量本身
block循环引用
block对象通过copy关键字修饰的,所有当前对象对block强引用,block内使用的变量又被当前对象强引用,相当于block强引用当前对象,这样就形成了引用循环
通过__weak修饰可以解决循环引用的问题,
根据block捕获变量的特性,会连其所有权修饰符一起捕获,这样,当我们使用__weak修饰时,__weak修饰符会被捕获到block中,这样,block与变量变成了弱引用关系,当变量被释放后,block也会被被释放

浙公网安备 33010602011771号