iOSIOS新手进阶

iOS底层探索之Block(五)——Block源码分析(__bl

2021-09-02  本文已影响0人  俊而不逊

回顾

在上一篇博客中,通过对block追根溯源,汇编跟踪调式,源码分析,对底层结构和 block的属性方法都有一定的认识, 那么本篇博客将继续对block的底层进行分析。

Block探索分析
iOS底层探索之Block(一)——初识Block(你知道几种Block呢?)

iOS底层探索之Block(二)——如何解决Block循环引用问题?

iOS底层探索之Block(三)——Block的本质

iOS底层探索之Block(四)——Block的探索和源码分析

1. block底层探索

block的结构和签名都分析完了,但是block最难的点还是怎么捕获到变量等。

cpp查看底层结构

再去瞄一眼底层结构,如下代码:

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSObject *objc = [NSObject alloc];
    void (^jp_block)(void) = ^{
        NSLog(@"zjpreno: %@ ",objc);
    };
    jp_block(); 
}

@end

通过 xcrun -sdk iphonesimulator clang -S -rewrite-objc -fobjc-arc -fobjc-runtime=ios-14.2 ViewController.m 命令生成.cpp文件

ViewController.cpp
通过生成的.cpp文件可以看到

底层结构分析

cpp对应源码中的Block_descriptor信息
这个 cpp的结构体即对应源码中的Block_descriptor信息。

2. block源码分析

在源码中搜索_Block_object_assign,找到如下注释信息:

_Block_object_assign注释信息
Block 被复制到堆时,一个Block 可以引用四种不同的需要帮助的东西。
  1. 基于C++堆栈的对象
  2. Objective-C 对象的引用
  3. 其他块
  4. __block 变量

在这些情况下,辅助函数由编译器合成,用于 Block_copyBlock_release,称为复制处置辅助函数。 复制助手为基于 C++堆栈的对象发出对C++ const 复制构造函数的调用,并为其余调用运行时支持函数_Block_object_assigndispose helper调用 C++析构函数用于情况 1,调用 _Block_object_dispose用于其余情况。

parameters

_Block_object_assign_Block_object_disposeflags 参数设置为:

如果 __block 变量被标记为weak,则编译器也在 BLOCK_FIELD_IS_WEAK (16)

所以 Block copy/dispose helper 应该只生成 37824 四个标志值。

上面是源码的注释,那么现在去验证一下:

验证
cpp我们也可以看到对于 OC 对象,是 BLOCK_FIELD_IS_OBJECT (3),那么我们现在去加一下__block,看看会不会变成 BLOCK_FIELD_IS_BYREF (8)呢?
__block验证
看到没有,加了__block之后就变成 BLOCK_FIELD_IS_BYREF (8),还有谁,45 度仰望天花板,我这该死无处安放的魅力啊!
666

_Block_object_assign

对比分析

_Block_byref_copy

_Block_byref_copy

Block_byref_2

cpp文件中这两个函数的实现如下:

keep方法和destory实现
 _Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 131);

(char*)dst + 40)相当于 objec,指针平移

对比

上面的 40 是怎么来的呢?如下:

内存大小
__Block_byref_id_object_copy_131方法的调用会调用_Block_object_assign函数,对Block_byref结构体中的对象进行BLOCK_FIELD_IS_OBJECT流程处理。

_Block_object_dispose

对于_Block_object_dispose方法,也就是释放流程,也是类似的。

_Block_object_dispose
也是对block类型的判断,再调用_Block_release(object)走释放流程。 _Block_release flags parameter

3. 总结

block 的三层拷贝

更多内容持续更新

🌹 喜欢就点个赞吧👍🌹

🌹 觉得有收获的,可以来一波,收藏+关注,评论 + 转发,以免你下次找不到我😁🌹

🌹欢迎大家留言交流,批评指正,互相学习😁,提升自我🌹

上一篇 下一篇

猜你喜欢

热点阅读