首页 > 代码库 > block 结构(1)
block 结构(1)
一个block其实是一个对象,有他自己的属性,结构如下
- isa指针,所有对象都有该指针,用于实现消息传递等功能(ias一般指向父类、元类)
- flags,用于按bit位表示一些block的附加信息
- reserved,保留变量。
- invoke,函数指针,指向具体的block实现的函数调用地址。
- descriptor, 表示该block的附加描述信息,主要是size大小,以及copy和dispose函数的指针。
- variables,capture过来的变量,block能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。
我们借助 clang -rewrite-objc 命令反编译.m文件得到.cpp文件,.m包含以下代
-(void )test3{ NSString *_person2=@"person2"; NSLog(@"block init:%@,%p,%p",_person2,&_person2,_person2); void (^myBlock)(int) = ^(int num) { NSLog(@"block excuteing:%@,%p,%p",_person2,&_person2,_person2); }; _person2=@"person22"; NSLog(@"block excutebefore:%@,%p,%p",_person2,&_person2,_person2); myBlock(1); NSLog(@"block excuteafter:%@,%p,%p",_person2,&_person2,_person2);}
得到部分源代码
//这里应该是注册代码中的常量,下面会用到
#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_0 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"KDBlockTest dealloc",19};static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_1 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"person2",7};static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_2 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"block init:%@,%p,%p",19};static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_3 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"block excuteing:%@,%p,%p",24};static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_4 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"person22",8};static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_5 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"block excutebefore:%@,%p,%p",27};static __NSConstantStringImpl __NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_6 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"block excuteafter:%@,%p,%p",26};
//imp:函数指针,指向具体block实现的函数
//_person2:截获的变量
//isa、flags、funcptr、desc后面会说道。
struct __KDBlockTest__test3_block_impl_0 { struct __block_impl impl; struct __KDBlockTest__test3_block_desc_0* Desc; NSString *_person2; __KDBlockTest__test3_block_impl_0(void *fp, struct __KDBlockTest__test3_block_desc_0 *desc, NSString *__person2, int flags=0) : _person2(__person2) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; }
//block实现的函数
static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, int num) { NSString *_person2 = __cself->_person2; // bound by copy NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_3,_person2,&_person2,_person2); }
//copy函数,可以拷贝到堆上
static void __KDBlockTest__test3_block_copy_0(struct __KDBlockTest__test3_block_impl_0*dst, struct __KDBlockTest__test3_block_impl_0*src) {_Block_object_assign((void*)&dst->_person2, (void*)src->_person2, 3/*BLOCK_FIELD_IS_OBJECT*/);}
//对应的释放函数
static void __KDBlockTest__test3_block_dispose_0(struct __KDBlockTest__test3_block_impl_0*src) {_Block_object_dispose((void*)src->_person2, 3/*BLOCK_FIELD_IS_OBJECT*/);}
//block对象的描述信息(大小等等)
static struct __KDBlockTest__test3_block_desc_0 { size_t reserved; size_t Block_size; void (*copy)(struct __KDBlockTest__test3_block_impl_0*, struct __KDBlockTest__test3_block_impl_0*); void (*dispose)(struct __KDBlockTest__test3_block_impl_0*);} __KDBlockTest__test3_block_desc_0_DATA = { 0, sizeof(struct __KDBlockTest__test3_block_impl_0), __KDBlockTest__test3_block_copy_0, __KDBlockTest__test3_block_dispose_0};
//这是objc测试函数test
static void _I_KDBlockTest_test3(KDBlockTest * self, SEL _cmd) { NSString *_person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_1; NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_2,_person2,&_person2,_person2); void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA, _person2, 570425344); _person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_4; NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_5,_person2,&_person2,_person2); ((void (*)(__block_impl *, int))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock, 1); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_6,_person2,&_person2,_person2);}
简单分析:
1).block初始化,结合构造函数:
__KDBlockTest__test3_block_impl_0(void *fp, struct __KDBlockTest__test3_block_desc_0 *desc, NSString *__person2, int flags=0) : _person2(__person2) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; }
void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA, _person2, 570425344);
传入了参数:函数指针、block描述、外部变量_person2,这时候在block内部对_person2进行了深拷贝(其实我也没从哪里看出来到底是深拷贝,希望大神赐教)
2).执行block
((void (*)(__block_impl *, int))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock, 1);
其实还是调用了block函数指针 所指向的函数__KDBlockTest__test3_block_func_0,并把block自己作为参数传递进去。
static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, int num) { NSString *_person2 = __cself->_person2; // bound by copy NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_51f509_mi_3,_person2,&_person2,_person2); }
值得注意的的是,我们在执行之前对_person2修改,但是并没有对block内部产生影响,因为在构造block的时候,block内部对截获的变量已经做了深拷贝,执行block的时候,直接调用函数__KDBlockTest__test3_block_func_0,函数内部,是引用了block拷贝的_person2对象,我想这应该就是block截获变量的特性
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。