美文网首页
iOS底层 -- Blcok本质之变量捕获

iOS底层 -- Blcok本质之变量捕获

作者: happy神悦 | 来源:发表于2020-09-09 09:20 被阅读0次

    1.auto变量

    int a = 10;
    void (^block)(void) = ^{
       NSLog(@"%d", a);
    };
    block();
    
    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
      int a; //这是新加入的成员变量
      __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    在_main_block_impl_0这个结构体中我们发现多了一个int类型的成员变量a,在结构体的构造函数中多了一个参数int _a,并且用这个int _a去初始化成员变量a,所以传入了自动变量a用来初始化_main_block_impl_0的成员变量a,_main_block_impl_0的成员变量a就被赋值为10了。

    2.static变量

    static int a = 10;
    void (^block)(void) = ^{
        NSLog(@"%d", a);
    };       
    block();
    
    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
      int *a;
      __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_a, int flags=0) : a(_a) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    在结构体多了一个指针类型的成员变量int *a,然后在构造函数中,将传递过来的&a,赋值给这个指针变量。也就是说,在_main_block_impl_0这个结构体中多了一个成员变量,这个成员变量是指针,指向a这个变量。所以当a变量的值发生变化时,能够得到最新的值。

    3.全局变量

    int height = 10;
    int main(int argc, char * argv[]) {
        @autoreleasepool {
            void (^block)(void) = ^{
                NSLog(@"%d", height);
            };
            block();
            return 0;
        }
    }
    
    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;
      }
    };
    

    在_main_block_impl_0结构体中并没有增加成员变量,所以可以得出结论,block并不会捕获全局变量。

    总结

    变量类型 是否捕获到block内部 访问方式
    局部auto变量 值传递
    局部static变量 指针传递
    全局变量 直接访问

    思考:为什么对于不同类型的变量,block的处理方式不同呢?

    这是由变量的生命周期决定的。对于自动变量,当作用域结束时,会被系统自动回收,而block很可能是在超出自动变量作用域的时候去执行,如果之前没有捕获自动变量,那么后面执行的时候,自动变量已经被回收了,得不到正确的值。对于static局部变量,它的生命周期不会因为作用域结束而结束,所以block只需要捕获这个变量的地址,在执行的时候通过这个地址去获取变量的值,这样可以获得变量的最新的值。而对于全局变量,在任何位置都可以直接读取变量的值。

    相关文章

      网友评论

          本文标题:iOS底层 -- Blcok本质之变量捕获

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