首页 > 代码库 > (转载)OC学习篇之---循环引用问题

(转载)OC学习篇之---循环引用问题

在之前的一片文章中,我们介绍了数组操作对象的时候引用问题以及自动释放池的概念,今天我们继续来看一下引用计数中一个痛疼的问题:循环引用

关于循环引用的问题,这里就不做太多解释了,就是多个对象之间相互引用,形成环状。

来看一个具体的例子:Dog类和Person类之间相互引用

Dog.h

 1 //   2 //  Dog.h   3 //  29_CyclePointer   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import <Foundation/Foundation.h>  10   11 #import "Person.h"  12   13 @interface Dog : NSObject  14   15 //这里不用retain,如果使用retain的话,会形成循环引用  16 @property(nonatomic,assign,readwrite) Person *person;  17   18 - (void)dealloc;  19   20 @end

Dog.m

 1 //   2 //  Dog.m   3 //  29_CyclePointer   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import "Dog.h"  10   11 @implementation Dog  12   13 - (void)dealloc{  14     //[_person release];  15     NSLog(@"dog dealloc");  16     [super dealloc];  17 }  18   19 @end

Dog类中有一个Person类型的属性

Person.h

 1 //   2 //  Person.h   3 //  29_CyclePointer   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import <Foundation/Foundation.h>  10   11 @class Dog;  12   13 @interface Person : NSObject  14   15 @property(nonatomic,retain,readwrite) Dog *dog;  16   17 - (void)dealloc;  18   19 @end

Person.m

 1 //   2 //  Person.m   3 //  29_CyclePointer   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import "Person.h"  10   11 #import "Dog.h"  12   13 @implementation Person  14   15 - (void)dealloc{  16     [_dog release];  17     NSLog(@"Person dealloc");  18     [super dealloc];  19 }  20   21 @end  

Person类中有Dog类型的属性

看一下测试代码

main.m

 1 //   2 //  main.m   3 //  29_CyclePointer   4 //   5 //  Created by jiangwei on 14-10-13.   6 //  Copyright (c) 2014年 jiangwei. All rights reserved.   7 //   8    9 #import <Foundation/Foundation.h>  10   11 #import "Dog.h"  12 #import "Person.h"  13   14 //循环引用  15 //是一个很麻烦的一件事,完全靠经验  16 int main(int argc, const charchar * argv[]) {  17       18     Person *p = [[Person alloc] init];  19     Dog *dog = [[Dog alloc] init];  20       21     [p setDog:dog];//dog计数:2  22       23     [dog setPerson:p];//person计数:2  24       25     [p release]; //person计数:1  26     [dog release];//dog计数:1  27       28     //没有释放的原因是dealloc方法中没有被执行,里面的释放代码也就没执行了,dog和person各自在等待,形成环状了  29     //解决版本就是切断他们之间的联系  30     //@property中不使用retain,使用assgin  31       32     NSLog(@"is over");  33       34     return 0;  35 }
 

我们分别定义了一个Person对象和Dog对象,然后相互引用了,但是当我们调用他们的release方法的时候,这两个对象并没有被释放。

原因很简单:person和dog的相互引用了,当执行release方法的时候引用计数都还是1,所以就不会调用dealloc方法了。dealloc方法中没有被执行,里面的释放代码也就没执行了,dog和person各自在等待,形成环状了

解决的办法是,切断他们之间的联系:在一方中定义属性的时候,@property中不使用retain,使用assgin。同时在dealloc方法中不再调用release方法了。

上面的例子中,我们可以看到Dog类中就是使用assgin。

 

总结

循环引用是对象销毁的时候遇到的最大的一个问题,在java中,垃圾回收器也会遇到这样的问题,所以就不采用引用计数法去管理对象了,而是另外的一种方式去管理。

(转载)OC学习篇之---循环引用问题