• iOS-block什么时候需要对变量使用__block


    什么时候需要对变量使用__block?

    __block可以用于解决block内部无法修改auto变量值的问题。__block不能修饰全局变量、静态变量(static)。

    __block用来赋值场景(对象类型)(使用场景修改auto变量值)

    //赋值场景
    NSMutableArray *__block array = nil;
    
    void(^Block)(void) = ^{
        array = [NSMutableArray array];
    };
    
    Block();
        

    使用场景修改auto变量值(基本数据类型)和底层实现

    __block int age = 10;
    __block NSObject *obj = [[NSObject alloc] init];
    
    void (^block)(void) = ^{
        obj = nil;
        age = 20;
    };

    上面的代码会被编译为:

    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
      __Block_byref_obj_1 *obj; // by ref
      __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;
      }
    };
    
    struct __Block_byref_age_0 {
      void *__isa;
    __Block_byref_age_0 *__forwarding;
     int __flags;
     int __size;
     int age;
    };
    
    struct __Block_byref_obj_1 {
      void *__isa;
    __Block_byref_obj_1 *__forwarding;
     int __flags;
     int __size;
     //内存管理
     void (*__Block_byref_id_object_copy)(void*, void*);
     void (*__Block_byref_id_object_dispose)(void*);
     NSObject  *obj;
    };
    
    //实际执行的block代码
    static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
      __Block_byref_obj_1 *obj = __cself->obj; // bound by ref
      __Block_byref_age_0 *age = __cself->age; // bound by ref
    
                (obj->__forwarding->obj) = __null;
                (age->__forwarding->age) = 20;
            }

    可见,__block修饰的变量会被包装成一个对象。

    问题:block在修改NSMutableArray时,需不需要添加__block?

    //block里面添加数据 不需要使用__block 因为这是对地址进行的操作
    NSMultableArray *array = [NSMultableArray array];
    
    void(^Block)() = ^{
        [array addObject:@"1"];
    };
    
    Block();

    我们给array添加元素,是使用这个地址,而不是修改这个地址, 但是如果我们array = nil这样才会报错,所以如果赋值的话需要用__block

    __block变量的内存管理

    当block在栈上时,并不会对__block变量产生强引用。

    当block被copy到堆时:

    • 会调用block内部的copy函数
    • copy函数内部会调用_Block_object_assign函数
    • _Block_object_assign函数会对__block变量形成强引用(retain)[仅ARC, MRC不会retain]

    当block从堆中移除时:

    • 会调用block内部的dispose函数
    • dispose函数内部会调用_Block_object_dispose函数
    • _Block_object_dispose函数会自动释放引用的__block变量(release)
  • 相关阅读:
    Thinkphp 模板中使用自定义函数的方法
    thinkphp 邮件发送
    str_replace使用
    SQL备份一张表的数据
    error: Allowed memory size
    LitJson使用
    implode,explode的使用
    ModelState.AddModelError使用
    HTTP 错误 404.2
    验证码显示不出来,在THINKPHP中的使用
  • 原文地址:https://www.cnblogs.com/junhuawang/p/14951735.html
Copyright © 2020-2023  润新知