blcok可以理解为一个代码块,但实质上是一个对象,封装了函数调用以及函数调用环境的oc对象
定义一个简单的block:
void (^block)(void) = ^(void){
NSLog(@"this is a block");
};
block();
用clang通过命令行以
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc
把oc语言转换成c++底层代码并把强制转换如下:
void (*block)(void) = &__main_block_impl_0(__main_block_func_0,
&__main_block_desc_0_DATA));
block->FuncPtr(block);
- __main_block_impl_0是一个结构体包括内容如下:
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
// 构造函数(类似于OC的init方法),并把参数传进去,返回结构体对象
__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_impl 并不是一个指针也是一个结构体,其中isa是一个指针证明block是一个对象,其中FuncPtr是一个方法调用调用自己的方法
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
另外一个__main_block_desc_0是一个结构体指针,里面的两个参数之一的Block_size代表的是一个block的内存大小
struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
};
2.第一个参数__main_block_func_0封装了block执行逻辑的函数也就是{}内部执行的函数,也就是构造函数的void *fp,地址赋值给了impl的FuncPtr,所以FuncPtr也就是执行block函数的地址
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_2r__m13fp2x2n9dvlr8d68yry500000gn_T_main_c60393_mi_0);
}
3.第二个参数是定义了一个 __main_block_desc_0_DATA结构体变量,赋值给了reserved ,sizeof(struct __main_block_impl_0)计算了__main_block_impl_0的size,并赋值给了我Block_size
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)};