请看如下代码: Dog.h #import <Foundation/Foundatio.h> @class Person; //声明一个Person类,仅仅是一个声明 @interface Dog : NSObject @property(nonatomic, retain) Person *owner; //拥有owner属性 @end Person.h #import <Foundation/Foundatio.h> @class Dog; //声明一个Dog类,仅仅是一个声明 @interface Person : NSObject @property(nonatomic, retain) Dog *dog; //拥有dog属性 @end main.m //创建对象 Dog *d = [Dog new]; Person *p = [Person new]; //循环引用 p.dog = d; d.owner = p; //看似正确的释放代码 [d release]; [p release]; 但是程序执行结果是p和d都没有释放掉 原理分析: p和d创建结束后,计数器都为1 执行p.dog = d后,set方法中执行了[_dog retain], dog计数器加1,变为2 执行d.owner = p后,set方法中执行了[_owner retain], owner计数器加1,变为2 当执行了[d release], [p release]后,dog和owner的引用计数器都变为1,不能释放,出现错误 总结: 循环retain的场景: 比如A对象ratain了B对象,B对象retain了A对象 循环retain的弊端:会导致A和B对象永远无法释放 循环retain的解决方案: 当两端互相引用时,应该一端用retain,一端用assign 分析原因: 比如上面的例子中,Person一端用assign的时候,在set方法中会直接赋值,不会调用[_owned retain],计数器仍为1 执行[p release],计数器变为0,调用dealloc方法,在dealloc方法中,执行[_dog release],dog的计数器减为0,内存释 放。 |