zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    2017-2018-1 20155326 实验四 外设驱动程序设计
    2017-2018-1 20155326 20155320《信息安全技术》实验四 木马及远程控制技术
    20155326 2017-2018-1 《信息安全系统设计基础》第六章课上考试题
    6月20日云栖精选夜读:阿里怎么发工资?自研薪酬管理系统首次曝光
    一个成功的研发团队应具备的9大属性
    那些创业的艰辛整理
    明明可以靠脸吃饭偏要靠才华_你身边有女神程序员吗?
    程序猿们_一二三四线城市你更愿意选择去哪里工作?
    微服务架构实践之邮件通知系统改造
    谈谈“僵尸猎手小明”手游兼容性踩到的坑
  • 原文地址:https://www.cnblogs.com/junhuawang/p/14951735.html
Copyright © 2011-2022 走看看