拜伦的博客

Coder Byron

这里有关于iOS,机器学习的笔记心得,欢迎交流


iOS底层(5)-Block

目录

Block本质

本质是一个OC对象,编译之后是一个结构体包含isa指针,block中封装了调用的函数和调用环境。调用环境值variables是block捕获的变量(如果block中访问了一些需要被捕获的变量,例如局部变量) block的变量捕获机制:

  • 局部变量, auto临时变量会捕获到block内部,且用的值传递。static 会捕获,用的指针传递。
  • 全局变量,不会捕获,block运行的时候会直接访问

auto临时变量代表 autorelease的在一个作用域内的临时变量

1

其中FuncPtr指的block函数的指针。 block分为3种类型,分别为__NSGlobalBlock____NSStackBlock____NSMallocBlock__,分为位于以下内存区域,那么什么样的block会属于什么样的类型?

2

3

上图表示不同的block因为操作的变量类型不一样,所以block类型也不一样。因为auto变量是临时变量会存在stack中自动销毁,所以相应block就是stack。没访问auto变量则存在常量区global

为什么block用copy修饰?

由于stackblock在栈中,且捕获的是在栈中的变量,如果变量销毁,有可能block访问的就的数据就是野指针,所以需要将stackblock通过调用copy方法转为mallocblock即保存到堆中,保证由用户自己创建自己销毁,不会造成程序异常。所以block变量用copy修饰或者直接调用copy方法

block如果捕获变量

当block内部访问了对象类型的auto变量时:

  • 如果block在栈上,则不会对auto变量强引用
  • 如果block被拷贝到堆上:会调用block内部的copy函数(__block_object_assgin),会根据对象的修饰符__strong, __weak等作出强引用或弱引用
  • 如果block从堆上移除:调用block内部dispose函数,对变量release

__block与__weak、__strong

__block修饰一个变量会把他包装成一个结构体对象,其中的一个属性就是这个变量。且这个结构体对象会把捕获的对象进行引用,根据对象前面是否使用__weak__strong 决定是弱引用还是强引用。 block中的forwarding指针是指向自己位于堆中的地址,如果修饰的是对象,block中还会增加2个内存管理方法,copydispose

__weak 和 __strong 目的是在变量被block捕获的时候以什么引用方式。

循环引用问题:

对象 强引用 block; block 强引用 对象 导致无法释放, 解决办法是将其中一条链路变为弱引用,则能完成释放。

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦