这是一个有趣的问题。我有一个视图控制器,我们称之为 MyViewController。它的成员之一是一个自定义视图,我们称之为 MyCustomView。MyCustomView 还具有对其父级 MyViewController 的引用,因为 MyViewController 用作自定义视图的委托。卸载 MyViewController 时会出现问题,例如由于内存警告。这是发生的事情:
首先,为 MyViewController 调用 viewDidUnload。它看起来像这样:
- (void)viewDidUnload {
[super viewDidUnload];
self.myCustomView = nil;
self.someData = nil;
...
}
当 self.myCustomView = nil 被执行时,它会触发 myCustomView 被释放。MyCustomView 的 dealloc 例程如下所示:
- (void)dealloc {
...
[delegate release];
...
[super dealloc];
}
回想一下,委托是 MyViewController。如果首先释放 MyCustomView,这不会有问题,因为 MyViewController 的引用计数将大于 1,但在这种情况下,MyViewController 已经没有其他引用了。这会导致 MyViewController 被释放,即调用它的 dealloc 例程,如下所示:
- (void)dealloc {
[myCustomView release];
[somedata release];
...
[super dealloc];
}
如您所见,MyViewController 的成员,即“somedata”在 MyViewController 的 viewDidUnload 例程完成之前获得释放。随着 MyViewController 和 MyCustomView 的 dealloc 例程完成,我们回到完成 viewDidUnload 例程,我们开始
self.somedata = nil;
现在,somedata 不是 nil,但它的值已经被释放了!这会导致异常。
这似乎是引用计数中的一个严重缺陷。您如何处理像这样的对象中导致彼此被释放的双向引用?
一种答案是在 dealloc 例程中始终将成员设置为 nil。我不喜欢这个答案。这是很多额外的工作,大部分时间都不需要。另一个答案是重新排列 viewDidUnload 的顺序,以便可能具有向后指针的子对象的释放总是在最后发生。我也不喜欢这个解决方案,有时它甚至可能不起作用。
你如何解决这个问题?