OC对象 - Block内存管理

OC对象 - Block内存管理

1. block从栈拷贝到堆

  • 当block在栈上时,并不会对__block变量产生强引用
  • 当block被copy到堆时
    1. 会调用block内部的copy函数
    2. copy函数内部会调用_Block_object_assign函数
    3. _Block_object_assign函数会对__block变量形成强引用(retain)

1.1 分析

  • 假设有__block变量Block0Block1都使用__block变量
  • 此时__block变量Block0Block1都是在栈上,Block0Block1并没有对__block变量产生强引用
  • Block0复制到堆上时,同时会把__block变量复制到堆上,并且强引用__block变量

  • 接着Block1也复制到堆上时,在此之前__block变量已经复制到堆上了,Block1此时也会强引用__block变量

2 block从堆中移除

  • 当block从堆中移除时
    1. 会调用block内部的dispose函数
    2. dispose函数内部会调用_Block_object_dispose函数
    3. _Block_object_dispose函数会自动释放引用的__block变量(release)

2.1 分析

2.1.1 单个block持有
  • Block从堆中移除时,会释放引用的__block变量
  • 此时__block变量没有其他持有者了,因此也销毁了

2.1.2 多个block持有
  • Block0Block1都持有__block变量
  • Block0从堆中移除时,会释放对__block变量的引用
  • 此时__block变量还被Block1引用着
  • Block1也从堆中移除,也释放对__block变量的引用
  • 此时__block变量没有其他持有者了,因此也销毁了

3. block的__forwarding指针

使用__block修饰的变量,编译器会将__block变量包装成一个对象,对象对应的结构体如下

注意到里面的__forwarding,并且在修改值的时候,它也是通过访问包装对象的__forwarding,再访问将要操作的变量

3.1 原因

block使用过程中,是可能从栈上拷贝到堆上的,__forwarding是指向自己的指针,当block在栈上时,他指向的是栈上的自己


block拷贝到堆上后,栈上的block__forwarding指向复制到堆上的__block变量用结构体的指针,堆上的block__forwarding指向的还是自己本身的指针

这就可以保证,block复制到堆上后,不管使用栈上的block,还是堆上的block,都能通过__forwarding访问堆上的block

4. 对象类型的auto变量 VS 添加__block修饰符的变量

__block int age = 10;
        
ZSXPerson *person = [[ZSXPerson alloc] init];
    
ZSXBlock block = ^ {
    age = 20;
    NSLog(@"age is %d", age);
    NSLog(@"person is %d", person);
};

4.1 当block在栈上时,对它们都不会产生强引用

4.2 当block拷贝到堆上时,都会通过copy函数来处理它们

  • __block变量(假设变量名叫做a)
    1. _Block_object_assign((void*)&dst->a, (void*)src->a, 8/BLOCK_FIELD_IS_BYREF/);
  • 对象类型的auto变量(假设变量名叫做p)
    1. _Block_object_assign((void*)&dst->p, (void*)src->p, 3/BLOCK_FIELD_IS_OBJECT/);

4.3 当block从堆上移除时,都会通过dispose函数来释放它们

  • __block变量(假设变量名叫做a)
    1. _Block_object_dispose((void*)src->a, 8/BLOCK_FIELD_IS_BYREF/);
  • 对象类型的auto变量(假设变量名叫做p)
    1. _Block_object_dispose((void*)src->p, 3/BLOCK_FIELD_IS_OBJECT/);

@oubijiexi

  • 26
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值