美文网首页
iOS 开发_深入浅出的剖析Block三、Block原理探索

iOS 开发_深入浅出的剖析Block三、Block原理探索

作者: iOS_PM_WEB_尛鹏 | 来源:发表于2018-12-20 16:53 被阅读0次

    【作者前言】:13年入圈,分享些本人工作中遇到的点点滴滴那些事儿,17年刚开始写博客,高手勿喷!以分享交流为主,欢迎各路豪杰点评改进!

    1.应用场景:

    Block经常被应用于设计模式,界面传值,代码块绑定,增强项目灵活性,提升代码B格等

    2.实现目标:

    理解Block的探索

    3.代码说明:

    1)其实被_ _Block修饰过的变量,修改的并非是原变量
        __block int a = 10;///> 其实被__block修饰过的变量,其本身已经就GameOver了.在临时的编译区间就已经不存在了,而在block作用域代码块之中有新的区间在等着你....
    
        NSLog(@"原本的外部作用域中的a:%p",&a);
        void (^block)(void) = ^{
            a ++;//这里修改的并非外部空间的变量地址,而是copy--->修改新的空间地址
            NSLog(@"Block作用域中的a:%p",&a);
        };
        block();
        NSLog(@"Block作用域处理后的a:%p",&a);
    
    控制台输出佐证:
    原本的外部作用域中的a:0x16d8dd378
    
    Block作用域中的a:0x1d422d9d8
    
    Block作用域处理后的a:0x1d422d9d8
    
    2)编译过程中的底层源码探索

    ①在一个路径下,通过命令行创建一个testBlock.c文件
    WorkZyp-MacBook-Pro:testBlock zyp$ vim testBlock.c
    开启输入模式 i --->输入以上内容的c形式代码

    #include "stdio.h"
      
    int main() {
        __block int a = 10;
        void(^block)(void) = ^{
            a++;
            printf("hello testBlock");
        };
        block();
    }
    
    

    Esc--->:wq 保存退出

    ②gcc 编译执行
    WorkZyp-MacBook-Pro:testBlock zyp$ gcc testBlock.c

    ③利用clang静态分析编译过程中的底层源码
    WorkZyp-MacBook-Pro:testBlock zyp$ clang -rewrite-objc testBlock.c -o testBlock.cpp

    到这里对编译过程的文件处理已经结束,这时在所选的路径下会出现以下三个文件:如图所示


    image.png

    打开testBlock.cpp文件 查看并静态的分析底层编译源码

    int main() {
        //对应 __block int a = 10;
        __attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 10};
        /**对应
         void(^block)(void) = ^{
            a++;
            printf("hello testBlock");
         };
         */
    //&a可以看出对作用域中的变量是地址的传递,以及后续是拷贝新空间对新变量进行处理
        void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
        //对应  block();
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    
    }
    
    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
      __Block_byref_a_0 *a; // by ref  可以看出是利用指针对新地址的变量进行修改
      __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_a_0 *_a, int flags=0) : a(_a->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    struct __Block_byref_a_0 {
      void *__isa;
    __Block_byref_a_0 *__forwarding;
     int __flags;
     int __size;
     int a;
    };
    
    

    相关文章

      网友评论

          本文标题:iOS 开发_深入浅出的剖析Block三、Block原理探索

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