Objective-C Block
<<<<<<==========================>>>>>>
- 如果有如下代码片段:
NSInteger valOfCopy = 4; __block NSInteger valOfAddress = 5; [self setBock:^{ NSLog(@"Test Block ---- valOfCopy: %d", valOfCopy); NSLog(@"Test Block ---- valOfAddress : %d", valOfAddress); }];
通过 clang -rewrite-objc 生成的c++代码如下:
<<<<<<==========================>>>>>>
- block 实现定义,每一个block都以此结构开始
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; };
isa: 指向 _NSConcreteStackBlock
FuncPtr: 为block实现的c方法指针:
- 所有使用 __block 修饰的变量都会有如下结构体:
struct __Block_byref_valOfAddress_0 { void *__isa; __Block_byref_valOfAddress_0 *__forwarding;/* 链表 */ int __flags; int __size; NSInteger valOfAddress; };
- 每一个block定义都有一个Desc的如下结构体:
static struct __EZLNAtomicObj__testBlock_block_desc_0 { size_t reserved; size_t Block_size; void (*copy)(struct __EZLNAtomicObj__testBlock_block_impl_0*, struct __EZLNAtomicObj__testBlock_block_impl_0*); void (*dispose)(struct __EZLNAtomicObj__testBlock_block_impl_0*); } __EZLNAtomicObj__testBlock_block_desc_0_DATA = { 0, sizeof(struct __EZLNAtomicObj__testBlock_block_impl_0), __EZLNAtomicObj__testBlock_block_copy_0, __EZLNAtomicObj__testBlock_block_dispose_0};
- 每一个block的定义类似如下结构体:
struct __EZLNAtomicObj__testBlock_block_impl_0 { struct __block_impl impl; struct __EZLNAtomicObj__testBlock_block_desc_0* Desc; NSInteger valOfCopy; //by value __Block_byref_valOfAddress_0 *valOfAddress; // by ref __EZLNAtomicObj__testBlock_block_impl_0(void *fp, struct __EZLNAtomicObj__testBlock_block_desc_0 *desc, NSInteger _valOfCopy, __Block_byref_valOfAddress_0 *_valOfAddress, int flags=0) : valOfCopy(_valOfCopy), valOfAddress(_valOfAddress->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } };
- 函数指针类型定义
static void __EZLNAtomicObj__testBlock_block_func_0(struct __EZLNAtomicObj__testBlock_block_impl_0 *__cself) { __Block_byref_valOfAddress_0 *valOfAddress = __cself->valOfAddress; // bound by ref NSInteger valOfCopy = __cself->valOfCopy; // bound by copy NSLog((NSString *)&__NSConstantStringImpl__var_folders_k6__hvncg2s7db50p8ngrh2dxhh0000gn_T_EZLNAtomicObj_bd52cc_mi_5, valOfCopy); NSLog((NSString *)&__NSConstantStringImpl__var_folders_k6__hvncg2s7db50p8ngrh2dxhh0000gn_T_EZLNAtomicObj_bd52cc_mi_6, (valOfAddress->__forwarding->valOfAddress)); }
- block 调用代码
NSInteger valOfCopy = 4; __attribute__((__blocks__(byref))) __Block_byref_valOfAddress_0 valOfAddress = {(void*)0,(__Block_byref_valOfAddress_0 *)&valOfAddress, 0, sizeof(__Block_byref_valOfAddress_0), 5}; ((void (*)(id, SEL, void (*)()))(void *)objc_msgSend)((id)self, sel_registerName("setBock:"), ((void (*)())&__EZLNAtomicObj__testBlock_block_impl_0((void *)__EZLNAtomicObj__testBlock_block_func_0, &__EZLNAtomicObj__testBlock_block_desc_0_DATA, valOfCopy, (__Block_byref_valOfAddress_0 *)&valOfAddress, 570425344))); void (*Block1)(void) = ((void (*)())&__EZLNAtomicObj__testBlock_block_impl_1((void *)__EZLNAtomicObj__testBlock_block_func_1, &__EZLNAtomicObj__testBlock_block_desc_1_DATA)); ((void (*)(id, SEL, void (*)()))(void *)objc_msgSend)((id)self, sel_registerName("setBock:"), (void (*)())((id (*)(id, SEL))(void *)objc_msgSend)((id)Block1, sel_registerName("copy")));
总结:block实际是一个C++对象,包含了blok里引用的变量(值复制)和指针结构体(使用__block修饰),整个block结构体类似一个C++对象,提供一个带参数的构造函数。执行block实际上是对block对象发消息,然后将block的对象作为参数传入,而block对象又定义了一个函数指针,实际上是执行此函数。
无论遇到什么困难、一往直前