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};
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1 Block机制 (Very Good) Block技巧与底层解析 http://www.jianshu.com...
    Kevin_Junbaozi阅读 4,143评论 3 48
  • Block基础回顾 1.什么是Block? 带有局部变量的匿名函数(名字不重要,知道怎么用就行),差不多就与C语言...
    Bugfix阅读 6,885评论 5 61
  • 前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这...
    小人不才阅读 3,844评论 0 23
  • We take a minute to have a crush on somene but a lifetime...
    RaleighSu721阅读 174评论 0 1
  • 迎春花后七里香,栀子花接着凤凰花开。毕业季-6月来了,校园广播里离别的歌曲回荡着的时候,就莫名的伤感。看过好多离别...
    想听风往哪边跑阅读 299评论 0 0

友情链接更多精彩内容