Block 是什么?它内部的数据结构是什么样的?
我这边写了一个 BlockTestClass 类里面的代码如下:
#import "BlockTestClass.h"
@implementation BlockTestClass
- (void)testMethods{
void (^BlockMethod)(int input) = ^(int input){
NSLog(@"%d",input);
};
if (BlockMethod) {
BlockMethod(2026);
}
}
@end
打开终端 cd 到 BlockTestClass.m 所在文件夹执行下面的代码将 OC 转换成 C++ 执行完之后会在当前文件夹新增一个 BlockTestClass.cpp 文件
clang -rewrite-objc BlockTestClass.m
得到 c++代码
// - (void)testMethods;
/* @end */
#pragma clang assume_nonnull end
// @implementation BlockTestClass
struct __BlockTestClass__testMethods_block_impl_0 {
struct __block_impl impl;
struct __BlockTestClass__testMethods_block_desc_0* Desc;
__BlockTestClass__testMethods_block_impl_0(void *fp, struct __BlockTestClass__testMethods_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __BlockTestClass__testMethods_block_func_0(struct __BlockTestClass__testMethods_block_impl_0 *__cself, int input) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_mf_mbzvp10j21vggsw04my_j31m0000gn_T_BlockTestClass_9d202b_mi_0,input);
}
static struct __BlockTestClass__testMethods_block_desc_0 {
size_t reserved;
size_t Block_size;
} __BlockTestClass__testMethods_block_desc_0_DATA = { 0, sizeof(struct __BlockTestClass__testMethods_block_impl_0)};
static void _I_BlockTestClass_testMethods(BlockTestClass * self, SEL _cmd) {
void (*BlockMethod)(int input) = ((void (*)(int))&__BlockTestClass__testMethods_block_impl_0((void *)__BlockTestClass__testMethods_block_func_0, &__BlockTestClass__testMethods_block_desc_0_DATA));
if (BlockMethod) {
((void (*)(__block_impl *, int))((__block_impl *)BlockMethod)->FuncPtr)((__block_impl *)BlockMethod, 2026);
}
}
// @end
通过上面的代码 Block 是封装了函数和上下文的结构体对象
它会根据 类名方法名_block_impl_下标 (0代表这个方法或者这个类中第0个block 下面如果还有将会 第1个block 第2个…)
一个变量被 __block 修饰的区别?
@implementation BlockTestClass
- (void)testMethodsTwo {
__block int a = 10;
void (^BlockMethodTwo)(void) = ^{
a += 1;
NSLog(@"a=%d",a);
};
if (BlockMethodTwo) {
BlockMethodTwo();
}
}
输出结果 a=11
继续生成对应的 c++文件
// __block 变量的底层结构
// @implementation BlockTestClass
struct __Block_byref_a_0 {
void *__isa;
__Block_byref_a_0 *__forwarding;// 关键!指向自身的指针
int __flags;
int __size;
int a;
};
多了一个 __Block_byref_a_0
block 将变量包装成结构体,通过 forwarding 指针实现在堆栈间正确访问
理解这些底层机制有助于编写正确、高效的 Block 代码