如何释放包含引用其父级的视图的视图控制器

时间:2010-11-12 23:09:12

标签: iphone objective-c memory-management uiviewcontroller didreceivememorywarning

这是一个有趣的问题。我有一个视图控制器,我们称之为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;

现在,有些数据不是零,但它的价值已经被释放了!这会导致异常。

这似乎是引用计数的一个关键缺陷。你如何处理这样的对象中的双向引用,导致彼此解除分配?

一个答案是始终在dealloc例程中将成员设置为nil。我不喜欢那个答案。这是一项额外的工作,大部分时间都不需要。另一个答案是重新排列viewDidUnload的顺序,以便可能具有向后指针的子对象的释放总是在最后发生。我也不喜欢这种解决方案,有时甚至可能都无法工作。

你如何解决这个问题?

1 个答案:

答案 0 :(得分:5)

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

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

如果你让你的代表这样你就不会有问题。它应该是安全的,因为父视图控制器只与子视图一样长 - 是吗?