循环引用

顾名思义,就是相互引用,循环了,释放的时候,无法释放,才会导致内存泄漏。

1.例子:
举个例子,我写一个控制器和一个类,它两个相互导入头文件,并各自拥有对方的一个属性。


循环引用_第1张图片
QQ20170726-094214.png

循环引用_第2张图片
QQ20170726-094200.png

循环引用_第3张图片
QQ20170726-094150.png

在dealloc中打印,发现不执行dealloc,因为两个对象相互引用,控制器销毁的时候,需要先确保控制器上的东西销毁干净,所以需要先释放test对象,但是test释放又需要先确保它自己的东西销毁干净,所以需要先释放控制器vc。导致了2个对象谁也销毁不掉。
相当于A和B相约自杀,A说B你先自杀我再自杀去陪你,但是B说A你先自杀我接着自杀陪你,最后谁也说服不了谁,谁也死不了。就成了循环引用。

2.如何解决这个问题?这个问题产生的根源在于A和B都是对方的属性,并且strong修饰,强引用了对方,都是不可或缺的东西,只要不使用强引用,就能打破这个怪圈。
用weak修饰,只要一方用弱引用,被弱引用的一方对于另一方就是不重要的东西了。比如A强引用了B,B弱引用了A,俩人相约自杀,A让B先死自己才能自杀,由于B弱引用A,意味着A对B不重要,A的死活和自己没关系,所以B就先自杀了,然后A遵守约定,接着自杀了。
这个循环关系打破,内存就释放了。
看图:


QQ20170726-095649.png

循环引用_第4张图片
QQ20170726-095613.png

重点:解决问题的关键就是相互引用的时候,一个用strong,一个weak,打破相互强引用的关系。
另外:如果B强引用了A,A没有引用B,只是在使用的时候,把B初始化在代码里,当成了局部变量,这也不会引起循环引用,因为都不存在相互引用!
如图:


循环引用_第5张图片
QQ20170726-100234.png

循环引用_第6张图片
QQ20170726-100222.png

3.原因找到了,但是使用的时候,怎么去分配谁强谁弱?
先有爹还是先有儿子?当然是爹先存在了。所以谁先存在谁就强引用另外一个!
页面加载一般都是控制器的代码先执行,所以控制器先存在,控件是在控制器加载完后代码才执行的,所以是控制器强引用控件。
问题来了:如果控制器弱引用了控件会怎么样?


循环引用_第7张图片
QQ20170726-101753.png

如图,控件strong了控制器,控制器weak了控件,一强一弱,上面说过了,这种情况是不会循环引用的。结果证明确实如此。但是,报警告。并且打印为null。
为什么呢?应为弱引用不是强制占有,初始化之后就立即自动释放掉了导致了这个对象不存在。对象都不存在了,它的属性也就不存在了,所以就打印null了。
又有问题了?为什么控件弱引用控制器就不会自动释放呢?
因为控制器已经存在了,不需要去初始化。如果是weak修饰,系统就默认这个东西不重要,就算初始化了,也给你立马释放。但是如果这个东西已经提前存在了,再去用weak修饰,系统就无可奈何了。不会去自动释放。
假如我在控件的代码里去初始化这个vc,也会报这个错误


循环引用_第8张图片
QQ20170726-102612.png

3.观察xib的代码发现,如果控件是用xib拖线拖出来的,发现这个控件是用weak修饰的,有点怪。
这是应为xib是已经存在的东西了,它比控制器还早,是控制器的爹了。默认xib 强引用了控制器,所以控制器才用weak修饰了xib控件。(感觉是这个原因,瞎扯的,估计大概是这个意思)

你可能感兴趣的:(循环引用)