1、什么是循环引用?循环引用会导致什么问题?
- 相互持有,双方都无法释放,导致循环引用,A强引用着B,B强引用着A
- 循环引用导致双方无法释放,从而导致内存泄露
下面来看下block中的循环引用
self.quoteBlock = ^{
NSLog(@"%ld",self.age);
};
quoteBlock是类的属性(后面称这个类为A),所以A强引用着quoteBlock。因为quoteBlock捕获了self这个局部变量,对self产生了一个强引用(对self捕获不明白的可以看我这篇文章Block对象变量捕获(三)),所以quoteBlock强引用着A。于是就产生了A强引用着quoteBlock,quoteBlock强引用着A,循环引用的问题。
1、A释放时需要将它引用的quoteBlock先释放,于是A通知quoteBlock释放
2、quoteBlock接收到释放通知后,就准备将自己释放,但是此时它又强引用着A,于是它又要将它引用的A先释放,于是quoteBlock又通知A释放
3、A需要等待强引用下的quoteBlock先释放,quoteBlock又需要等待它强引用下的A先释放,于是就产生了相互等待的情况,谁也无法释放。
2、解决block下的循环引用问题
- 原理就是打破任何一方的强引用,就能解决循环引用
__weak typeof(self) weakSelf = self;
self.quoteBlock = ^{
NSLog(@"%ld",weakSelf.age);
};
在self对象前加了个__weak修饰,block内部就不会对A产生强引用,当block被释放时__weak会自动为nil,不需要block再去释放A了。
1、A释放时通知quoteBlock释放
2、quoteBlock因为没有强引用A,所以无需通知A并等待A先释放,quoteBlock接收到释放通知后就立马释放
3、quoteBlock释放后,A也跟着释放,所以就解决了循环引用的问题
更多解决block循环引用的方法可以看这位大佬的如何解决Block循环引用问题?,其他的方法了解一下就好,最好的方法还是__weak。
下面是我相关的Block文章,大家有兴趣的也可以看下
Block变量捕获详解(一)
Block的三种类型(二)
Block对象变量捕获(三)
__block修饰符(四)