假设我们有三个对象:祖父母,父母和子女。祖父母保留父母,父母保留子女,孩子保留父母。祖父母释放父母。
在这种情况下会发生什么?
[除非对父母或孩子有其他提及,否则他们都会成为孤儿。但是,父级和子级之间的保留周期会阻止它们之一释放,并且它们成为浪费的内存。
孩子永远不要保留父母。如果有的话,请在子级中使用弱引用来维护对父级的引用。
[保留周期为条件,当两个对象相互引用并被保留时,由于两个对象试图相互保留,因此无法释放,因此它创建了一个保留周期。
此处“祖父母”保留“父母”,“父母”保留“孩子”,而“子女”保留“父母”。在这里,在父母与孩子之间建立了保留周期。释放祖父母后,父母和孩子都成为孤儿,但是父母的保留计数不会为零,因为孩子正在保留它,因此会导致内存管理问题。
有两种可能的解决方案:
1)使用指向父级的弱指针,即,子级应使用对父级的弱引用,但不保留。
2)使用“关闭”方法打破保留周期。
http://www.cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html
在一个简单的例子中,考虑两个对象A和B,其中A创建并保留B。创建A时,它创建B。当创建A的任何人最终释放它时,A的保留数都降为零,并被释放。如果A的dealloc方法调用B的release,则B的保留计数也将降为零,并且也会被释放。 [这假设没有其他人保留A或B,因为我保持简单。]
但是如果B需要引用A并保留A会怎样?创建A的人可能会释放它。但是由于B也保留了A,因此A的保留数不会为零。同样,由于A保留了B,因此B的保留计数也不会为零。两者都不会被释放。即使B在自己的dealloc中调用A的release方法也没关系,因为永远不会调用该方法。
此时,您会发生内存泄漏,因为即使它们仍然存在,也没有对A或B的引用。如果A或B正在做任何占用大量处理器资源的操作,那么您可能还会将CPU时间浪费在不需要的对象上。
在您的情况下,A是父母,B是孩子,创建的任何人都是祖父母。
[保留周期是当对象A保留对象B,而对象B保留对象A时发生的循环。在这种情况下,如果释放了任何一个对象:
因此,即使在一切正常的情况下,这两个对象也应该在程序的生命周期内徘徊,即使它们在一切正常的情况下也应该被释放。
[当祖父母释放父母时,父母仍然活着,因为孩子保留父母。
Retain Cycle是当2个对象相互引用并被保留时的条件,它创建了一个保留周期,因为两个对象试图互相保留,因此无法发布。
示例:一个人住在一个部门中,一个部门有一个人。
@class Department;
@interface Person:NSObject
@property (strong,nonatomic)Department * department;
@end
@implementation Person
-(void)dealloc{
NSLog(@"dealloc person");
}
@end
@interface Department: NSObject
@property (strong,nonatomic)Person * person;
@end
@implementation Department
-(void)dealloc{
NSLog(@"dealloc Department");
}
@end
然后这样称呼它:
- (void)viewDidLoad {
[super viewDidLoad];
Person * person = [[Person alloc] init];
Department * department = [[Department alloc] init];
person.department = department;
department.person = person;
}
您将不会看到dealloc日志,这是保留圈。
祖父母:约翰父母:特德儿童:玛丽
这是我的示例,使用电话进行说明:
John打电话给Ted,想和Mary进行电话会议。
Ted对John说:“挂断电话,我会拨玛丽的电话”
Ted使John处于保留状态,并呼叫立即接听电话的Mary。