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什么时候执行完毕