block的声明以及使用的底层实现

2020-04-18  本文已影响0人  LaoQianYJ

1. 在OC中block的声明->赋值->使用

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            声明:
            void (^block)(int count);
            返回值 变量名 参数
            
            赋值:
                     返回值 参数 {要执行的代码}
            block = ^void(int count) {
                count++;
                NSLog(@"count=%d, 地址:%p", count, &count);
            };
        
            使用:
            变量名(参数);
            block(count);
        }
    }
    

2. block的底层实现

    在cmd中进入到当前文件所在目录,利用clang(LLVM编译器),将OC代码转换成C/C++代码;
    clang -rewrite-objc main.m
    会在同级目录下生成一个main.cpp的文件,在其中我们就能找到我们需要的代码;
    主要包含了以下3个结构体和1个函数以及main函数的实现,在main函数中我们就能分析OC的block在底层的实现
    
    struct __block_impl {
        void *isa; // 指向_NSConcreteStackBlock/NSConCreteMallocBlock/NSConCreteGlobleBlock类创建的实例
        int Flags; // 标识符
        int Reserved; // 保留字段
        void *FuncPtr; // block{}中函数实现的函数指针
    };
    
    static struct __main_block_desc_0 {
        size_t reserved; // 保留字段
        size_t Block_size; // 表示该结构体占据多少孔家
    };
    
    struct __main_block_impl_0 {
        struct __block_impl impl;
        struct __main_block_desc_0 *Desc;
        // 初始化
        // fp: 是block{}中的代码实现
        // desc: 是block的描述信息(所占用的内存空间大小)
        // flags: 标识符
        __main_block_impl_0(void *fp, struct __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, int count) {
        count++;
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_7x_02rxw4ms63z1hyly7yn3nj040000gn_T_main_672f2f_mi_0, count, &count);
    };
    
    int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        // 声明 一个C语言的指针变量
        void (*block)(int count);

        int count = 10;
        // 赋值 创建__main_block_impl_0结构体 调用__main_block_impl_0的函数进行初始化,并进行强制类型转换,转换为 (void (*)(int))即C语言的函数指针
        block = ((void (*)(int))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
        
        // 调用,实际是执行了__main_block_func_0函数
        ((void (*)(__block_impl *, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, count);
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_7x_02rxw4ms63z1hyly7yn3nj040000gn_T_main_672f2f_mi_1, count, &count);

    }
    return 0;
}

3. 总结

    block实际就是C语言的函数指针,只是用3个结构体来表示OC对象
    所以表面上来看block是一个匿名函数,实际上在底层它还是有函数名称的

声明:参考文章https://juejin.im/post/5cc0050cf265da035948746d

上一篇下一篇

猜你喜欢

热点阅读