block的生成与调用记录

void nc_test() {
    
    void (^block1)(NSString *) = ^(NSString *str_a){
        NSLog(@"----%@",str_a);
    };
    block1(@"abc");  


    int (^block2)(int) = ^(int a){
        return a*2;
    };  
    int b = block2(123);
 
}

用clang -rewrite-objc main.m转化上面代码

void nc_test() {


    void (*block1)(NSString *) = ((void (*)(NSString *))&__nc_test_block_impl_0((void *)__nc_test_block_func_0, &__nc_test_block_desc_0_DATA));

    ((void (*)(__block_impl *, NSString *))((__block_impl *)block1)->FuncPtr)((__block_impl *)block1, (NSString *)&__NSConstantStringImpl__var_folders_s__2lbjj8zs1md0wqmlr3w4zndr0000gn_T_main_76bab1_mi_2);


    int (*block2)(int) = ((int (*)(int))&__nc_test_block_impl_1((void *)__nc_test_block_func_1, &__nc_test_block_desc_1_DATA));

    int b = ((int (*)(__block_impl *, int))((__block_impl *)block2)->FuncPtr)((__block_impl *)block2, 123);

}

先关注下block1

查看与block1相关的几个结构:

struct __nc_test_block_impl_0 {
  struct __block_impl impl;
  struct __nc_test_block_desc_0* Desc;
  __nc_test_block_impl_0(void *fp, struct __nc_test_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __nc_test_block_func_0(struct __nc_test_block_impl_0 *__cself, NSString *str_a) {
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_s__2lbjj8zs1md0wqmlr3w4zndr0000gn_T_main_76bab1_mi_1,str_a);
    }

static struct __nc_test_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __nc_test_block_desc_0_DATA = { 0, sizeof(struct __nc_test_block_impl_0)};

回到block1的初始化:
    void (*block1)(NSString *) = ((void (*)(NSString *))&__nc_test_block_impl_0((void *)__nc_test_block_func_0, &__nc_test_block_desc_0_DATA));

可以看到是通过__nc_test_block_impl_0() 函数生成了一个对象再强转为(void (*)(NSString *))类型然后赋值给block1。

查看__nc_test_block_impl_0()

struct __nc_test_block_impl_0 {
  struct __block_impl impl;
  struct __nc_test_block_desc_0* Desc;
  __nc_test_block_impl_0(void *fp, struct __nc_test_block_desc_0 *desc, int flags=0) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

__nc_test_block_impl_0()是__nc_test_block_impl_0的构建函数,调用时需要传入两个必传参数(void *fp, struct __nc_test_block_desc_0 *desc)
__nc_test_block_impl_0结构体下包含两个子结构,分别为__block_impl、__nc_test_block_desc_0类型

struct __block_impl {
  void *isa;
  int Flags;
  int Reserved;
  void *FuncPtr;
};

isa指针指向&_NSConcreteStackBlock,代表block的类型
FuncPtr指向的是block中内容的实现地址,调用block时真正调用的方法地址,__nc_test_block_impl_0结构体构建时第一个参数void *fp,就是赋值给FuncPtr的。

static struct __nc_test_block_desc_0 {
  size_t reserved;
  size_t Block_size;
} __nc_test_block_desc_0_DATA = { 0, sizeof(struct __nc_test_block_impl_0)};

__nc_test_block_desc_0主要存储了block的大小,此处在编译时就构建了一个__nc_test_block_desc_0类型的对象__nc_test_block_desc_0_DATA,
也就是block1生成时调用__nc_test_block_impl_0()时传入的两个参数之一(&__nc_test_block_desc_0_DATA),另一个参数是(void *)类型的__nc_test_block_func_0

static void __nc_test_block_func_0(struct __nc_test_block_impl_0 *__cself, NSString *str_a) {

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_s__2lbjj8zs1md0wqmlr3w4zndr0000gn_T_main_76bab1_mi_1,str_a);
    }

所以block1的初始化就是通过__nc_test_block_impl_0结构体的构建函数,生成一个__nc_test_block_impl_0的对象。

再看block1的调用:
    ((void (*)(__block_impl *, NSString *))((__block_impl *)block1)->FuncPtr)((__block_impl *)block1, (NSString *)&__NSConstantStringImpl__var_folders_s__2lbjj8zs1md0wqmlr3w4zndr0000gn_T_main_76bab1_mi_2);

首先关于后面一长串( (NSString *)&__NSConstantStringImpl__var_folders_s__2lbjj8zs1md0wqmlr3w4zndr0000gn_T_main_76bab1_mi_2),由于调用block时传入的参数是@"abc",为常量字符串,那一串则为常量字符串的存储地址。
然后去掉大量的类型转换:
((block1)->FuncPtr)(block1,&@"abc" );
也就是对block1结构体下的FuncPtr指向的函数的直接调用。也就是直接调用了初始化block1时传入的第一个参数__nc_test_block_func_0

static void __nc_test_block_func_0(struct __nc_test_block_impl_0 *__cself, NSString *str_a) {

        NSLog((NSString *)&__NSConstantStringImpl__var_folders_s__2lbjj8zs1md0wqmlr3w4zndr0000gn_T_main_76bab1_mi_1,str_a);
    }

关于长长的那两串都是代表代码中出现的常量字符串("abc"、"----%@"):

static __NSConstantStringImpl __NSConstantStringImpl__var_folders_s__2lbjj8zs1md0wqmlr3w4zndr0000gn_T_main_76bab1_mi_1 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"----%@",6};
static __NSConstantStringImpl __NSConstantStringImpl__var_folders_s__2lbjj8zs1md0wqmlr3w4zndr0000gn_T_main_76bab1_mi_2 __attribute__ ((section ("__DATA, __cfstring"))) = {__CFConstantStringClassReference,0x000007c8,"abc",3};

你可能感兴趣的:(block的生成与调用记录)