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对象又定义了一个函数指针,实际上是执行此函数。

 

posted @ 2018-03-26 09:25  茄菲兔  阅读(126)  评论(0编辑  收藏  举报