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

2018-12-20  本文已影响0人  iOS_PM_WEB_尛鹏

【作者前言】: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;
};

上一篇下一篇

猜你喜欢

热点阅读