Block实现
来源:互联网 发布:关键字排名优化软件 编辑:程序博客网 时间:2024/06/01 17:14
block是如何实现的
我们通过clang编译出Objective-C文件对应cpp文件,去看他的实现方式,对比不同样式的block
的不同,
从中得到它的实现思想
无参数Block的基本实现
#import "ViewController.h"typedef void(^WxsBlock) ();@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; WxsBlock blockObj = ^(){ NSLog(@"test"); }; blockObj();}@end
我们在ViewController.m中声明,实现并使用一个不带参数的Block
然后通过clang编译出对应的cpp文件,我们只关心和Block对应的代码,如下
typedef void(*WxsBlock) ();struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr;};struct __ViewController__viewDidLoad_block_impl_0 { struct __block_impl impl; struct __ViewController__viewDidLoad_block_desc_0* Desc; __ViewController__viewDidLoad_block_impl_0(void *fp, struct __ViewController__viewDidLoad_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; }};static void __ViewController__viewDidLoad_block_func_0(struct __ViewController__viewDidLoad_block_impl_0 *__cself) { NSLog((NSString *)&__NSConstantStringImpl__var_folders_t9_g3xrsv653kz2gr7tmgwfbfvh0000gn_T_ViewController_dd8c22_mi_0);}static struct __ViewController__viewDidLoad_block_desc_0 { size_t reserved; size_t Block_size;} __ViewController__viewDidLoad_block_desc_0_DATA = { 0, sizeof(struct __ViewController__viewDidLoad_block_impl_0)};static void _I_ViewController_viewDidLoad(ViewController * self, SEL _cmd) { ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad")); WxsBlock blockObj = ((void (*)())&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA)); ((void (*)(__block_impl *))((__block_impl *)blockObj)->FuncPtr)((__block_impl *)blockObj);}
我们来解析一下
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr;}
这个结构体的作用相当于是一个block的“核心功能类”,包含指向superclass的指针,
执行方法的指针。
void *isa
指向superclass的指针,在Objective-C中Block也是对象,这个就不难理解了int Flags
标记,这个不知道有什么深意,暂且我们理解为做一个标记的作用。int Reserved
预留字段,现在不必关心,不过这种预留的思想可以学习void *FuncPtr
要执行方法的指针,这个是用来持有block代码块中方法的指针
static struct __ViewController__viewDidLoad_block_desc_0 { size_t reserved; size_t Block_size;} __ViewController__viewDidLoad_block_desc_0_DATA = { 0, sizeof(struct __ViewController__viewDidLoad_block_impl_0)};
__ViewController__viewDidLoad_block_desc_0
看名字,这是一个用来描述block的,
size_t reserved
预留的空间大小size_t Block_size
block的空间大小__ViewController__viewDidLoad_block_desc_0_DATA
声明的结构体变量,参数是reserved = 0
Block_size
是__ViewController__viewDidLoad_block_impl_0
的大小
struct __ViewController__viewDidLoad_block_impl_0 { struct __block_impl impl; struct __ViewController__viewDidLoad_block_desc_0* Desc; __ViewController__viewDidLoad_block_impl_0(void *fp, struct __ViewController__viewDidLoad_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; }}
看到impl这个应该是对应Implements,见名知意我们可以理解为声明一个block对应的类
struct __block_impl impl
就是我们上边描述的“核心类”struct __ViewController__viewDidLoad_block_desc_0* Desc
block的描述,主要描述block所占空间大小Block_size__ViewController__viewDidLoad_block_impl_0
是此结构体的一个构造函数void *fp
构造函数第一个参数,执行函数指针,赋值给impl
变量的funcPtr
指针struct __ViewController__viewDidLoad_block_desc_0 *desc
这里又作为构造函数的第二个参数,赋值给Desc
变量int flags=0
同上,赋值给impl
中的Flags
变量,但这有趣的是,它默认为0,深意自咎,因为我也猜不出来。。impl.isa = &_NSConcreteStackBlock;
这个对应的还有_NSConcreteGlobalBlock
_NSConcreteMallocBlock
这里我们只需要知道它对应的是在栈上的block,其他的我们后边解析
static void __ViewController__viewDidLoad_block_func_0(struct __ViewController__viewDidLoad_block_impl_0 *__cself) { NSLog((NSString *)&__NSConstantStringImpl__var_folders_t9_g3xrsv653kz2gr7tmgwfbfvh0000gn_T_ViewController_dd8c22_mi_0);}
static void __ViewController__viewDidLoad_block_func_0
静态block执行函数,也就是我们在{}
中的NSLog
那一段。struct __ViewController__viewDidLoad_block_impl_0 *__cself)
参数是我们刚才提到的impl
“核心功能类”,但是奇怪的是它并没有在函数体中使用,
这个我们看后边能否解答。- 中间的就不用说了,NSLog。。
WxsBlock blockObj = ((void (*)())&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA));
(void (*)())
标示无返回值的匿名函数指针,并且函数没有参数,这也正对应了我们前边的typedef void(*WxsBlock) ();
block声明&
这个取地址符我有点懵逼,来个懂C的大神指点一下(ps:默默的去看看大学的C课本。。),虽然看不懂,但是不影响我们的整体解读。__ViewController__viewDidLoad_block_impl_0
是__ViewController__viewDidLoad_block_impl_0
结构体的一个构造函数,也就是我们定义的block的一个构造函数。参数上边有说。__ViewController__viewDidLoad_block_func_0
里边是NSLog...
的那个函数指针,也就是我们在block体中写的代码逻辑指针。__ViewController__viewDidLoad_block_desc_0_DATA
是__ViewController__viewDidLoad_block_desc_0
声明是创建的一个描述对象
带参数Block实现
在.m文件中:
typedef void(^WxsBlock) (NSString *str,NSArray *arr);- (void)viewDidLoad { [super viewDidLoad]; WxsBlock blockObj = ^(NSString *str,NSArray *arr){ NSLog(@"test"); }; blockObj(@"wxs",[NSArray array]);}
通过clang编译后:
typedef void(*WxsBlock) (NSString *str,NSArray *arr);struct __ViewController__viewDidLoad_block_impl_0 { struct __block_impl impl; struct __ViewController__viewDidLoad_block_desc_0* Desc; __ViewController__viewDidLoad_block_impl_0(void *fp, struct __ViewController__viewDidLoad_block_desc_0 *desc, int flags=0) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; }};static void __ViewController__viewDidLoad_block_func_0(struct __ViewController__viewDidLoad_block_impl_0 *__cself, NSString *str, NSArray *arr) { NSLog((NSString *)&__NSConstantStringImpl__var_folders_t9_g3xrsv653kz2gr7tmgwfbfvh0000gn_T_ViewController_cf62af_mi_0);}static struct __ViewController__viewDidLoad_block_desc_0 { size_t reserved; size_t Block_size;} __ViewController__viewDidLoad_block_desc_0_DATA = { 0, sizeof(struct __ViewController__viewDidLoad_block_impl_0)};static void _I_ViewController_viewDidLoad(ViewController * self, SEL _cmd) { ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad")); WxsBlock blockObj = ((void (*)(NSString *, NSArray *))&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA)); ((void (*)(__block_impl *, NSString *, NSArray *))((__block_impl *)blockObj)->FuncPtr)((__block_impl *)blockObj, (NSString *)&__NSConstantStringImpl__var_folders_t9_g3xrsv653kz2gr7tmgwfbfvh0000gn_T_ViewController_cf62af_mi_1, ((NSArray *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSArray"), sel_registerName("array")));}通过对比看出,我们加入了两个参数,编译出来的cpp代码和之前的对照也只是在传参的地方有所不同,在实现和逻辑调用上并没有发生变化。
0 0
- block实现
- Block实现
- UIActionsheet的block实现
- block实现场景切换
- 【block第四篇】实现
- block 实现原理
- Block实现委托机制
- block底层实现原理
- Block的实现原理
- block的实现原理
- block实现原理详解
- block 实现原理详解
- block的实现原理
- Block实现原理
- block的底层实现
- Block实现原理
- block实现原理?
- Block实现iOS回调
- dhcp服务器
- python程序-->列表到字典的函数,针对好玩游戏物品清单
- 三分钟学会git bash命令行
- swift3 类class与结构体struct
- discuz模板机制
- Block实现
- Eclipse debug:F5、F6、F7、F8 作用
- -Dmaven.multiModuleProjectDirectory system property is not set
- go示例3:模拟简单游戏服务器
- 将博客搬至CSDN
- 如何在编译器(vs2013)里设置调用别人写好的lib和dll步骤
- SAP Business One与国内软件厂商产品对比
- android下的代码混淆
- 葛洲坝电力集团责任有限公司改变企业新句号