Block的本质

结论:Block的本质是结构体。

验证过程

1.C++转码

在viewDidLoad初始化一个Block,并且调用如下:

void(^block)(void) = ^{
   NSLog(@"block----");
};
    
block();

将Block代码所在文件转成C++代码。

打印Log

注:cd 你当前项目文件夹 -> xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc Block所在的文件 —> 回车

  • 生成如下文件


    ViewController.cpp

导入项目中,因为默认Xcode是不支持编译C++文件的,尝试编译会报一堆红

报错

点击Build Phases -> Compile Sources -> 删除导入的cpp文件 不参与编译

2.查看C++代码中OC Block初始化和调用部分。

search - > viewDidLoad 关键字

static void _I_ViewController_viewDidLoad(ViewController * self, SEL _cmd) {
    ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad"));

//声明
    void(*block)(void) = ((void (*)())&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA));

//调用
    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}
  • 简化一下去掉不必要的强制转化
//声明
void(*block)(void) = &__ViewController__viewDidLoad_block_impl_0(__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA));
//调用
block->FuncPtr(block);
分析 : block->FuncPtr指向的函数地址然后调用
分析 : __ViewController__viewDidLoad_block_impl_0 search
struct __ViewController__viewDidLoad_block_impl_0 {
  struct __block_impl impl;
  struct __ViewController__viewDidLoad_block_desc_0* Desc;
    //构造函数 - > 类似OC init  返回结构体
  __ViewController__viewDidLoad_block_impl_0(void *fp, struct __ViewController__viewDidLoad_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

这种函数称之为构造函数类似于OCinit初始化方法。构造函数返回的是结构体对象。结构体的地址赋值给了Block。

所以Block的本质是结构体。

C++ Block声明调用完整源码

struct __ViewController__viewDidLoad_block_impl_0 {
  struct __block_impl impl;
  struct __ViewController__viewDidLoad_block_desc_0* Desc;
    //构造函数 - > 类似OC init  返回结构体
  __ViewController__viewDidLoad_block_impl_0(void *fp, struct __ViewController__viewDidLoad_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

//Block 执行内部的逻辑函数
static void __ViewController__viewDidLoad_block_func_0(struct __ViewController__viewDidLoad_block_impl_0 *__cself) {

        //打印 内容 block---
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_1y__lhqj8pj6qx60xxbtx_r1z6w0000gn_T_ViewController_7b9f5e_mi_0);
    }

static struct __ViewController__viewDidLoad_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __ViewController__viewDidLoad_block_desc_0_DATA = { 0, sizeof(struct __ViewController__viewDidLoad_block_impl_0)};

static void _I_ViewController_viewDidLoad(ViewController * self, SEL _cmd) {
    ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad"));

    //声明
    void(*block)(void) = ((void (*)())&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA));

    //调用
    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}

推荐阅读更多精彩内容