概述
在iOS开发中Block使用比较广泛,对于使用以及一些常规的技术点这里不再赘述,主要利用C++角度分析Block内部数据底层实现,解开开发中为什么这样编写代码解决问题。
Block本质
Block本质也是一个OC对象,内部也有isa指针,最终继承NSObject。它是封装了函数调用以及函数调用环境的OC对象。
接下来编写一个Block,利用clang
编译器指令可以将我们编写的OC代码转换成C++代码,更好的看清Block地层结构。
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 定义block
void(^block)(void) = ^{
NSLog(@"-----------");
};
// 执行block
block();
}
return 0;
}
执行命令
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
上面编写OC代码转换成C++代码main.cpp
#pragma clang assume_nonnull end
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
// Block底层的结构
struct __main_block_impl_0 {
void *isa;
int Flags;
int Reserved;
void *FuncPtr; // 保存内部代码块执行的函数地址
// struct __block_impl impl;
struct __main_block_desc_0* Desc; // Block的信息
// 构造方法
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
// Block内部执行代码块封装的函数
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_zz_1js09xx15fz7j7qyrylx4xm80000gn_T_main_3df4b0_mi_0);
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)/*block自己结构的内存大小*/};
int main(int argc, const char * argv[]) {
/* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
// 定义block
// block真实类型 struct __main_block_impl_0 *
void(*block)(void) = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA);
// 执行block
block->FuncPtr(block);
}
return 0;
}