美文网首页
block自我理解1

block自我理解1

作者: 敲一手烂代码 | 来源:发表于2017-04-04 21:30 被阅读2次

    从最简单的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

          本文链接:https://www.haomeiwen.com/subject/rimzottx.html