Block的实现原理

参考:唐巧的博客

objective-c的底层是用C++实现的。

我们用clang命令是可以把objective-c代码转码为C++代码的。这成为了我们分析block实现原理的工具:

objective-c中一共有三种类型的block:

1._NSConcreteGlobalBlock 

2._NSConcreteStackBlock 

3._NSConcreteMallocBlock

NSConcreteGlobalBlock

GlobalBlock

全局的静态 block,不会访问任何外部变量。

NSConcreteStackBlock

栈block

保存在栈中的 block,当函数返回时会被销毁。

main_block_impl_0 中增加了一个变量 a,在 block 中引用的变量 a 实际是在申明 block 时,被复制到main_block_impl_0 结构体中的那个变量 a。因为这样,我们就能理解,在 block 内部修改变量 a 的内容,不会影响外部的实际变量 a。


__block对应的栈block

增加了下划线block后block实现方式发生了改变。

1.源码中增加一个名为 __Block_byref_i_0 的结构体,用来保存我们要 capture 并且修改的变量 i。

2.main_block_impl_0 中引用的是Block_byref_i_0 的结构体指针,这样就可以达到修改外部变量的作用。

NSConcreteMallocBlock

保存在堆中的 block,当引用计数为 0 时会被销毁。

NSConcreteMallocBlock 类型的 block 通常不会在源码中直接出现,因为默认它是当一个 block 被 copy 的时候,才会将这个 block 复制到堆中。以下是一个 block 被 copy 时的示例代码 (来自这里),可以看到,在第 8 步,目标的 block 类型被修改为 _NSConcreteMallocBlock。

变量的复制:

对于 block 外的变量引用,block 默认是将其复制到其数据结构中来实现访问的:

默认外部变量的引入方式

对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的:

__block修饰的外部变量引用方式


ARC 对 block 类型的影响

在 ARC 开启的情况下,将只会有 NSConcreteGlobalBlock 和 NSConcreteMallocBlock 类型的 block。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容