block的循环引用问题

循环引用示例

  • block会对block中的对象进行持有操作,如果block中的对象又持有了该block就会造成循环引用
  • 典型的场景就是block作为self的属性使用时,又在block调用了self的属性或方法,代码如下
//  Test.h
#import <Foundation/Foundation.h>

typedef void (^MyBlock)();

@interface Test

@property(nonatomic,copy) MyBlock blockTest;
@property(nonatomic,copy) NSString* name;

-(void)print;
@end
//  Test.m
#import "Test.h"

@implementation Test

-(void)print{
    self.blockTest = ^{
        NSLog(@"%@",self.name);
    };
    self.blockTest();
}
@end
  • 上例中,self和blockTest相互持有了对方,self的销毁依赖于blockTest的销毁,blockTest的销毁依赖于self的销毁,造成了循环引用

解决

  1. 在ARC下,使用__weak修饰符定义一个self的弱引用,并在block中使用弱引用可以解决循环引用问题,代码如下
-(void)print{
    __weak typedof(self) weakSelf = self;
    self.blockTest = ^{
        NSLog(@"%@",weakSelf.name);
    };
    self.blockTest();
}
  1. 但block的执行时间不确定,当block被执行的时候被__weak修饰的self对象可能已经被释放了,比如ViewController已经被pop了,在涉及异步和并发时这种情况有可能发生
  • 对于这种情况,应在block中使用__strong修饰符修饰self,这样在block执行期间持有对象,block执行结束后解除持有,代码如下:
-(void)print{
    __weak typedef(self) weakSelf = self;
    self.blockTest = ^{
        __strong typeof(self) strongSelf = weakSelf
        NSLog(@"%@",strongSelf.name);
    };
    self.blockTest();
}

block中使用self一定会引起循环引用?

  • 不一定,比如大多的GCD方法
  • 只有当block和self相互持有时才会导致循环引用
/*将block异步派发到主队列*/
dispatch_async(dispatch_get_main_queue(),^{
    [self doSomething];
});

上面self没有对GCD中的block进行持有,只是block持有了self的引用,因此不会造成循环引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值