美文网首页
block的声明以及使用的底层实现

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

作者: LaoQianYJ | 来源:发表于2020-04-18 13:29 被阅读0次

    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

    相关文章

      网友评论

          本文标题:block的声明以及使用的底层实现

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