说到Retain Circle,一种简单(也最常听到)的说法是:
当两个对象相互强引用的时候,就形成了retain circle:
它有一个发展变种:当三个或以上的对象依次强引用,形成闭环的时候,也形成retain circle:
retain circle之所以要避免,是因为它一旦形成,便会阻止circle中的所有对象被系统回收从而造成内存泄露。
以上是retain circle的一个简单介绍;那为什么retain circle一旦形成,circle中的对象就无法被系统回收呢?我们以retain circle的最简单形式:两个对象相互强引用(如图1),来理解它如何阻止这两个对象被系统回收。
假设现在有两个类,它们的定义如下:
假设在工程某处代码使用类ClassA和ClassB,如下:
现在假设代码对ClassA和ClassB的使用只局限在图4所示部分;于是,到最后一行 [objectA release];【注释1】执行了之后我们可以期待objectA和objectB被系统回收;但事与愿违。因为系统回收objectA(和objectB)的前提是它们的reference count为0的时候,ClassA和ClassB的dealloc方法被调用;但是当此处最后一行[objectA release];被调用的时候,objectA的reference count不为0,因为还有objectB在强引用着它;objectB的reference count亦不为0,因为还有objectA在强引用着它。于是它们(objectA和objectB)在相互等待对方被释放(同时释放自己),形成了类似线程模型中的死锁。
注释1:在开启了ARC的文件中,如果出现release语句,xcode会报编译错误;此处写法只是为了说明问题;另外,在xcode为我们编译代码的时候,会自动帮我们插入release,只是我们在编辑器里看不到而已。