1

这是一个有趣的问题。我有一个视图控制器,我们称之为 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 的顺序,以便可能具有向后指针的子对象的释放总是在最后发生。我也不喜欢这个解决方案,有时它甚至可能不起作用。

你如何解决这个问题?

4

1 回答 1

5

委托成员通常不被引用计数。通常声明是:

@property(nonatomic, assign) id<UITableViewDelegate> delegate

如果你让你的代表像这样,你就不会有问题。它应该是安全的,因为父视图控制器只存在于子视图中——是吗?

于 2010-11-12T23:13:58.043 回答