美文网首页
__block-修改变量

__block-修改变量

作者: 越天高 | 来源:发表于2020-10-27 09:33 被阅读0次

    01
    在block内部修改外部的变量,不可以直接修改,因为那个age的作用域和block执行函数不再同一个作用域,改成static,或者全局可以改
    如果不想用的话,就要用到__block关键字

    02本质

    __block可以用于解决block内部无法修改auto变量值的问题

    __block不能修饰全局变量、静态变量(static)

    编译器会将__block变量包装成一个对象

    Person *p = [Person new];
               __block int age = 10;
                block = ^{
                    age = 12;
                    NSLog(@"%i", age);12
                };
                block();
    
                NSLog(@"%@", age);12
    

    一旦我们使用了__block来修饰auto变量,block在内存中的结构就会发生改变,在捕获这个变量的时候,不是简单的传值了,int age = 10;也会对这句进行包装

     __attribute__((__blocks__(byref))) __Block_byref_age_0 age = {(void*)0,(__Block_byref_age_0 *)&age, 0, sizeof(__Block_byref_age_0), 10}
    
    struct __Block_byref_age_0 {
     void *__isa;
    __Block_byref_age_0 *__forwarding;//
    int __flags;
    int __size;
    int age;//外面的那个值放在这里
    };
    
    struct __main_block_impl_0 {
     struct __block_impl impl;
     struct __main_block_desc_0* Desc;
     __Block_byref_age_0 *age; // by ref指向那个结构体
     __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_age_0 *_age, int flags=0) : age(_age->__forwarding) {
       impl.isa = &_NSConcreteStackBlock;
       impl.Flags = flags;
       impl.FuncPtr = fp;
       Desc = desc;
     }
    };
    

    当我们设置12的时候他会先难道age那个指针,找到age结构体,然后在访问forwarding指针,然后找到age进行修改
    如果在block里面丢改NSMutableArry的内容不会报错,因为他是使用这个指针,而不是更改这个指针。

    [图片上传失败...(image-eaafca-1603369164698)]

    03细节

    外面的age和里面结构体的age是不是同一个age,
    我们可以手动将源码拿过来给让block转成我们自己手动的结构体,打印block结构体里面的age的地址不一样,而是和age结构体里面的age地址一样。但是苹果为了让开发者看起来age是同一个,直接打印出来的age是一样的。屏蔽了内部的实现

    typedef void(^MyBlock)(void);
    
    
    struct __block_impl {
      void *isa;
      int Flags;
      int Reserved;
      void *FuncPtr;
    };
    struct __Block_byref_age_0 {
      void *__isa;//8
        struct __Block_byref_age_0 *__forwarding;//8
     int __flags;//4
     int __size;//4
     int age;
    };
     struct __main_block_desc_0 {
      size_t reserved;
      size_t Block_size;
      void (*copy)(void);
      void (*dispose)(void);
     };
    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
    struct __Block_byref_age_0 *age; // by ref//0x0000000100580f20
        
    };
    int main(int argc, const char * argv[]) {
        @autoreleasepool
        {
            MyBlock block;
               __block int age = 10;
                block = ^{
                    age = 12;
                    NSLog(@"%p", &age);
                };
                block();
            struct __main_block_impl_0 *myBlock = (__bridge struct __main_block_impl_0 *)block;
            NSLog(@"%p", &age);
             
        }
        return 0;
    }
    
    打印结果

    可以计算出访问的age是我们这个age结构里面的age成员相当于他的地址加上10进制的20,

    相关文章

      网友评论

          本文标题:__block-修改变量

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