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)
  • 相关阅读:
    一次有益的敏捷XP失败
    web拖动Drag&Drop原理
    一次有益的敏捷尝试
    一次有益的敏捷XP失败
    异地分布式敏捷软件开发探讨分析
    web拖动Drag&Drop原理
    XP中一些基本概念的简介
    XP中的重要惯例和规则
    异地分布式敏捷软件开发探讨分析
    PySide教程:第一个PySide应用
  • 原文地址:https://www.cnblogs.com/junhuawang/p/14951735.html
Copyright © 2011-2022 走看看