OC对象 - Block 的本质

OC对象 - Block 的本质

block - 代码块,开发中常用来封装一段代码,在想要执行的时候再调用执行,也常用来做传值、事件传递等等,是不可或缺的一个特性。但是如果使用不当,容易造成循环引用等问题。那block底层到底是怎么实现的呢

1. block的本质

  • block本质其实是个OC对象,他内部也有isa指针
  • block是封装了函数调用以及函数调用环境的OC对象
  • block的底层结构是:

我们把block转成c++代码,来验证下它的底层结构

1.1 查看block底层实现

  • 写一个最基础的block
c 复制代码
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        void(^block)(void) = ^{
            printf("block~~~\n");
        };
        block();
    }
    return 0;
}
  • 转成c++代码

  • struct __block_impl impl对应的就是 block 的底层结构

1.1.1 初始化block

  • 刚刚声明的 block
scss 复制代码
void(^block)(void) = ^{
            printf("block~~~\n");
        };

实际上它转成了

scss 复制代码
void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));

他是初始化了一个__main_block_impl_0结构体,

__main_block_impl_0构造方法接收两个参数void *fpstruct __main_block_desc_0 *desc,可以看到此处代码传入的值是(void *)__main_block_func_0&__main_block_desc_0_DATA

这两个参数传进__main_block_impl_0后赋值给了 impl.FuncPtrDesc

  • (void *)__main_block_func_0对应的是:

其实就是把我们 block 里面所写的代码封装成函数传进去。

Desc则是block的描述信息,对应结构体__main_block_desc_0 reserved仅是个保留字段,Block_size则表示 block 的大小

1.1.2 调用block

我们初始化block后,通过block()调用了block

底层对应转成这样:

scss 复制代码
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

他实际上就是帮我们调用了刚刚初始化时传入的保存在impl.FuncPtr的函数

此时block里面的代码就被调用执行了

@oubijiexi

相关推荐
Mapleay3 分钟前
FE-BE 动态路机制之 DPCM 与 DAPM 协作
linux
IT大白鼠22 分钟前
Linux故障分析与排查:系统日志、启动故障与文件系统修复
linux·运维·服务器
老詹图解IT25 分钟前
统信 UOS 登录界面转圈闪退/卡登录等常见原因及处理
linux·服务器·网络
闫记康25 分钟前
Linux学习笔记day1
linux·笔记·学习
轻颂呀31 分钟前
进程间关系和守护进程
linux·网络
sbjdhjd36 分钟前
02 (中)| K8s Pod 生产化落地:从配置到优化全流程
linux·运维·云原生·kubernetes·开源·podman·kubelet
皓月盈江37 分钟前
Linux Ubuntu系统如何编辑Docker容器内的文件
linux·ubuntu·docker·容器·靶场·vulhub·编辑docker内文件
jingyu飞鸟43 分钟前
linux系统二进制安装MySQL 8.4、8.0版本数据库,配置crontab和xtrabackup数据库热备份脚本
linux·数据库·mysql
无限进步_1 小时前
从Multics到Linux:操作系统的自由之路
linux·运维·服务器
China_Yanhy1 小时前
【云原生实战】从零构建无节点 EKS:Karpenter 极简注入与全自动算力接管指南
linux·运维·云原生