【问题标题】:How to deallocate view controllers that contains a view that references its parent如何释放包含引用其父视图的视图控制器
【发布时间】:2010-11-12 23:09:11
【问题描述】:

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

你如何解决这个问题?

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 我认为你是对的。我正在努力想一个例子,我在多个地方使用委托对象,或者委托比它的父对象更持久,但我想不出一个。如果确实发生了,那可能是糟糕的设计。我的问题是我在任命代表方面并不总是一致的。有时我有相互引用的视图控制器,以便它们可以共享数据。在这种情况下,谁应该持有引用计数指针并不总是很清楚。我想我应该解决这个问题。
    • @Mike,约定是父对象始终持有指向子对象的“分配”指针。只要孩子在父母之前被释放,你就可以了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    相关资源
    最近更新 更多