block是什么? block本质其实是能够截获自动变量的匿名函数,是一个oc对象(结构体),结构体里面的isa指针指向自己的类,但是它和对象又有一定的区别. 对象一般分配在堆上,而block默认分配在栈上(其他情况下面会说明),Block是C的扩展,指向结构体__main_block_impl_0的指针,创建__main_block_impl_0结构体时会根据变量环境初始化结构体成员变量,由此来分配内存区域,截获变量,管理内存,以及一些copy操作.
block的结构
通过clang工具翻译oc代码可以看到block的结构体信息,具体含义见注释
#import "test.h"
@implementation test
//oc代码
- (instancetype)init {
if (self == [super init]) {
void(^testBlock)() = ^{
NSLog(@"hello world!");
};
testBlock();
}
return self;
}
@end
clang -rewrite-objc test.m
//clang翻译之后的截取代码
// @implementation test
//block指向__test__init_block_impl_0此结构体,block的入口
struct __test__init_block_impl_0 {
struct __block_impl impl; //见下面
struct __test__init_block_desc_0* Desc; //描述block信息的结构体
//结构体的构造函数,含有初始化参数
__test__init_block_impl_0(void *fp, struct __test__init_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock; //block 创建在栈区,因此父类为_NSConcreteStackBlock
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
//block实现的结构体
struct __block_impl {
void *isa; //指向所属的类
int Flags; //按位承载 block 的附加信息;
int Reserved; //保留变量
void *FuncPtr; //函数指针,指向block执行的函数
};
//block要执行的函数代码
static void __test__init_block_func_0(struct __test__init_block_impl_0 *__cself) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_gd_3sky2l_d5jv0t9ww_t8_w3680000gp_T_test_87f55d_mi_0);
}
//描述block信息结构体
static struct __test__init_block_desc_0 {
size_t reserved;
size_t Block_size;
}
//结构体变量
__test__init_block_desc_0_DATA = { 0, sizeof(struct __test__init_block_impl_0)};
// @end |