1、循环引用的种类
(1)自循环引用
(2)相互循环引用
(3)多循环引用
- 如何破除循环引用?
(1)避免产生循环引用
(2)在合适的时机手动断环处理 - 具体的解决方案有哪些?
(1)__weak(代理). __block(block中) __unsafe_unretain
(2)__block 在MRC下,不会增加引用计数,可以避免循环引用。
在ARC下,修饰对象会被强引用,无法避免循环引用,需要手动断环。
(3)__unsafe_unretain 修饰对象不会增加引用计数,可以避免循环引用,但是如果修饰的对象,在某一时刻被释放,会产生悬垂指针,造成内存泄漏。(不提倡使用)
- 是否遇到过循环引用,又是怎样解决的呢?
(1)NSTimer 中的循环引用问题
视图控制器中使用到了timer ,首相该对象会对timer 有一个强引用,而为timer添加回调事件后,timer对它的targate对象也有强引用,这样就出现了循环引用问题。同时当前线程的RunLoop对time也有一个强引用。
(2)解决方案?
分两种情况:
(1)非重复的定时器:
我们可以在定时器的回调方法调用invate方法并将其置为nil.
(2)重复的定时器:
利用weak指针被释放后,置为nil的特点。
在timer和对象之间创建一个中间对象。通过在中间对象的timer回调方法中,判断判断是否为空,如果是,就说明已经被释放,然后,将timer设置为空。
通过创建一个中间对象,让中间对象分别持有两个弱引用对象分别是timer\targate(原对象).然后timer的回调是在中间对象中进行回调的。在这个回调方法中,对targate 进行判断,如果存在,就把timer的回调给原对象,如果不存在,就将其time设置为无效,从而解除了runloop对timer的强持有,time对中间对象的强引用关系 。
-
block中的循环引用问题?
Block循环引用
解决方案:
(1)使用__weak 进行修饰
为什么使用__weak 之后,就能解决循环引用呢?
因为:block对对象类型的截获方式,是连同其所有权修饰符一起进行截获的。所以在block中所使用的也是__weak 所修饰的。
对于__block产生的循环引用,我们使用断环的方式。
这种方式的弊端就是,在没有调用Block时,该循环引用的会一直存在。断环
6.block 为什么会产生循环引用?
如果block对当前对象的某一个成员变量进行截获的话,他会连同它的所有权修饰符一起截获,这样block对其就有一个强引用。block又因为当前对象对block又一个强引用,这样就形成了自引用方式的循环引用。使用__weak 进行修饰。
如果说我们使用__block ,在ARC下也会产生循环引用。这种情况下,使用断环的方式,进行戒除循环引用。弊端:如果block不被调用,循环引用就会一直存在。