第一篇文章 Block深层剖析(一)介绍了Block的一些基础概念和用法。
第二篇文章 Block深层剖析(二)分析了最简单的Block源码。
第三篇文章 Block深层剖析(三) 介绍了Block截获的相关特点和__block说明符。
这篇文章将会介绍Block存储域和__block存储域。
通过前面的文章我们知道,Block转换为__main_block_impl_0的结构体类型的自动变量,__block变量转换为__Block_byref_val_0的结构体类型的自动变量。
结构体类型的自动变量 就是在栈上生成的改结构体类型的实例。
1.Block存储域
__main_block_imp_0结构体的成员变量isa的初始化:
impl.isa = &_NSConcreteStackBlock;
说明该Block的类为_NSConcreteStackBlock类。即Block语法生成的Block为_NSConcreteStackBlock类对象,并且设置对象的存储域在栈上。
_NSConcreteStackBlock 设置对象的存储域在栈上
_NSConcreteGlobalBlock 设置对象的存储域在数据区
_NSConcreteMallocBlock 设置对象的存储域在堆
Block类的copy操作
_NSConcreteStackBlock copy后 从栈复制到堆
_NSConcreteGlobalBlock copy后 什么也不做
_NSConcreteMallocBlock copy后 引用计数增加
2.__block存储域
- 在Block中使用__block变量时,最先将所有的Block配置在栈上,所以__block变量也会配置在栈上。
- 在Block从栈复制到堆上时,__block变量也会从栈上复制到堆上,并被改Block所持有。
-
当配置在堆上的Block被废弃,那么它所持有的__block变量也会被释放(在没有持有者的时候才会被释放)。
3.__forwarding
__block变量的结构体成员变量__forwarding存在的理由:
- 无论在Block语法中、Block语法外使用__block变量,都能顺利的访问同一个__block变量。
- 无论__block变量配置在栈上还是堆上,都能顺利的访问同一个__block变量。
这是因为:
当__block变量在栈上时,__forwarding是指向自身本身的指针。