Block-对象类型的auto变量

2020-10-27  本文已影响0人  越天高

01

typedef void(^MyBlock)(void);

int main(int argc, const char * argv[]) {
    @autoreleasepool
    {
        MyBlock block;
        
        {
            Person *p = [Person new];
           block = ^{
                NSLog(@"%@", p);

            };
        }
        
    }
    return 0;
}

ARC中对象变量在执行完作用域之后并没有被销毁,因为他会有一个强指针指向了原来那个对象,
如果我们访问使用下面的方式

            __weak Person *weakP = p;

就不会对外面的变量产生强引用,所以就不会影响他的生命周期

02

当block内部访问了对象类型的auto变量时
如果block是在栈上,将不会对auto变量产生强引用
如果block被拷贝到堆上
会调用block内部的copy函数
copy函数内部会调用_Block_object_assign函数
_Block_object_assign函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用
如果block从堆上移除
会调用block内部的dispose函数
dispose函数内部会调用_Block_object_dispose函数
_Block_object_dispose函数会自动释放引用的auto变量,断开对对象的引用(类似release)

03

当我们block访问的变量为简单的数据类型的时候,他的内部结构组成为下图,只有两个成员,


        MyBlock block;
        {
            Person *p = [Person new];
            int age = 10;
            block = ^{
                NSLog(@"%@", age);
            };
        }
        
static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
}

但是如果他访问的auto变量为对象类型的时候,这个结构体里面就多了两个成员,对内部要访问的对象做内存管理。

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
}

新建一个iOS项目来演示延时操作

Person *person = [Person new];
        __weak Person *weakP = person;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSLog(@"%@",person)
            });
            NSLog(@"%@", weakP);
            
        });

block什么释放对象,要看用强指针引用的block什么时候执行完毕

上一篇下一篇

猜你喜欢

热点阅读