block自我理解1

从最简单的block开始开起,有一些浅显的心得如下:
在main.m文件生成如下代码:

int main(int argc, const char * argv[]) {
    void(^blk)(void) = ^{NSLog(@"Block");};
    blk();
}

通过命令行翻译(clang -rewrite-objc main.m)
删除不必要代码得到如下的c++文件

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

struct __main_block_impl_0 {
    struct __block_impl impl;
    struct __main_block_desc_0* Desc;
    __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_c8_pr2fhjtd5kz0_53s61zxc_400000gn_T_main_c32327_mi_0);
}

static struct __main_block_desc_0 {
    size_t reserved;
    size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};

int main(int argc, const char * argv[]) {
    void(*blk)(void) = ((void (*)())&__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA));
    ((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
    ((blk)->FuncPtr)(blk);
    return 0;
}

在block上的代码 翻译后 主要是变成了静态函数__main_block_func_0
从生成的代码上观察主要变成了封装的若干结构体
从上到下依次观察结构体,
__block_impl结构体是系统默认规定的结构体,并不是该代码翻译过来的结构体,结构体内部有isa指针(通常通俗的理解,拥有isa指针都会是一个对象,也就是说block会成为一个对象的可能,但这里不深究) ,观察最后一个变量
void FuncPtr; void 类似于oc中的id类型 (万能指针) 但从系统给出的变量名字可以看出是一个函数指针 也就是说oc中的block转换成多个结构体进行封装的函数指针
也就是说我们可以仿照转换的代码进行构造block
按照生成的代码风格进行 仿造后 得到如下代码:

struct __block_impl {
    void *FuncPtr;
};

struct __main_block_impl_0 {
    struct __block_impl impl;
    __main_block_impl_0(void *fp) {
        impl.FuncPtr = fp;
    }
};

static void __main_block_func_0() {
    NSLog(@"Block");
}

int main(int argc, const char * argv[]) {
    struct __main_block_impl_0 s = __main_block_impl_0((void *)__main_block_func_0);
    void(*blk)(void) = ((void (*)())&s);
    ((void (*)())((__block_impl *)blk)->FuncPtr)();
    return 0;
}

该代码是在原有代码的基础上 删除了多余结构体变量 尽量做到最简化实现,在main函数上 是保持了翻译后的代码风格,看上去有些乱,在此基础上写了一个更易理解的调用形式如下:

int main(int argc, const char * argv[]) {
    struct __main_block_impl_0 s = __main_block_impl_0((void *)__main_block_func_0);
    void(*blk)(void) = (void (*)())s.impl.FuncPtr;
    blk();
    return 0;
}

从上述描述上看,起码最简单的block ,最终也会形成一种函数,只不过是通过函数指针的形式进行调用,综上,可以通俗的理解为
block=函数+若干结构体封装(内部有函数指针变量)

你可能感兴趣的:(block自我理解1)