block(二)-- 底层分析

2019-05-22  本文已影响0人  Ray_lawq

block(一):https://www.jianshu.com/p/b83574a8ef80
连接上文拿到block 的C++ 文件,内容如下:

那么我们第二章就慢慢分析这个C++文件。

__block 修饰的局部变量变成一个__Blcok_byref_c_0 的结构体,让我们看看这个结构体的实现:

  1. 我们可以很清楚的看到有一个 __frowatding 这个变量,它有什么用呢?
    它是一个桥梁,在Block 内部,先找到这个结构体,通过这个结构体的frowatding成员变量找到外部的局部变量

  2. 那么__frowatding在不同类型的Block指向有什么不同呢:

这样通过__forwarding,无论是在block内部还是外部,不管是堆上还栈,都能访问到同一个__block修饰的变量。

__testBlockA_block_func_0(是Block 内部的方法(代码块))

block 实现方法(__testBlockA_block_impl_0),入参中有2个默认参数(方法): __testBlockA_block_func_0和__main_block_desc_0_DATA

结论:
1. 局部变量不能在block 里边修改值,__block修饰的和全局变量可以。
2. 验证了__forwarding在__block 结构体的指向(上边__forwarding的指向结论)

另一参数(方法): __main_block_desc_0_DATA

我们可以看到__main_block_desc_0中存储着两个参数:reserved
和Block_size;并且reserved赋值为0而Block_size则存储着__main_block_impl_0的占用空间大小。最终将__main_block_desc_0结构体的地址传入__main_block_func_0中赋值给Desc。

让我们在看看__testBlockA_block_impl_0 主方法里边的实现:

首先我们看一下__block_impl第一个变量就是__block_impl结构体。 来到__block_impl结构体内部

我们可以发现__block_impl结构体内部就有一个isa指针。因此可以证明block本质上就是一个oc对象。而在构造函数中将函数中传入的值分别存储在__main_block_impl_0结构体实例中,最终将结构体的地址赋值给block。

接着通过上面对__main_block_impl_0结构体构造函数三个参数的分析我们可以得出结论:

  1. __block_impl结构体中isa指针存储着&_NSConcreteStackBlock地址,可以暂时理解为其类对象地址,block就是_NSConcreteStackBlock类型的。
  2. block代码块中的代码被封装成__main_block_func_0函数,FuncPtr则存储着__main_block_func_0函数的地址。
  3. Desc指向__main_block_desc_0结构体对象,其中存储__main_block_impl_0结构体所占用的内存。

那么block是怎么执行的?

通过上述代码可以发现调用block是通过block找到FunPtr直接调用,通过上面分析我们知道block指向的是__main_block_impl_0类型结构体,但是我们发现__main_block_impl_0结构体中并不直接就可以找到FunPtr,而FunPtr是存储在__block_impl中的,为什么block可以直接调用__block_impl中的FunPtr呢?
重新查看上述源代码可以发现,(__block_impl *)block将block强制转化为__block_impl类型的,因为__block_impl是__main_block_impl_0结构体的第一个成员,相当于将__block_impl结构体的成员直接拿出来放在__main_block_impl_0中,那么也就说明__block_impl的内存地址就是__main_block_impl_0结构体的内存地址开头。所以可以转化成功。并找到FunPtr成员。
上面我们知道,FunPtr中存储着通过代码块封装的函数地址,那么调用此函数,也就是会执行代码块中的代码。并且回头查看__main_block_func_0函数,可以发现第一个参数就是__main_block_impl_0类型的指针。也就是说将block传入__main_block_func_0函数中,便于重中取出block捕获的值。

此时已经基本对block的底层结构有了基本的认识,上述代码可以通过一张图展示其中各个结构体之间的关系。

block底层的数据结构也可以通过一张图来展示

参考文章:https://www.jianshu.com/p/92f15fc9301a

上一篇下一篇

猜你喜欢

热点阅读