Nib 创建的视图保留文件的所有者防止 UIViewController 的释放
Posted
技术标签:
【中文标题】Nib 创建的视图保留文件的所有者防止 UIViewController 的释放【英文标题】:Nib-created view retaining file's owner prevents deallocation of UIViewController 【发布时间】:2011-10-11 23:14:19 【问题描述】:我有一个想要释放的视图控制器(然后可能稍后在应用程序中重新分配)。问题是它的视图似乎对它有很强的引用,如下面的堆栈跟踪所示。视图是否需要在视图控制器之前被释放?如果是这样,我该怎么做?感谢您的帮助:)
代码:
- (void)setCurrentCourse:(Course *)newCourse
... Reference count management ...
// area of concern
if (currentCourse == nil)
[self.rvc.view removeFromSuperview];
[self.rvc release];
// HERE I want rvc to be deallocated, but the retainCount is one.
else
// This is where I allocate the rvc instance
self.rvc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:[NSBundle mainBundle] courseSelectionController:self];
[self.view addSubview:self.rvc.view];
来自覆盖的回溯 -(id)retain;
#0 -[RootViewController retain] (self=0x1bb610, _cmd=0x349b6814) at RootViewController.m:609
#1 0x340b1cdc in CFRetain ()
#2 0x341620c0 in __CFBasicHashStandardRetainValue ()
#3 0x34163440 in __CFBasicHashAddValue ()
#4 0x340b1ff8 in CFBasicHashAddValue ()
#5 0x340b6162 in CFSetAddValue ()
#6 0x340c3012 in -[__NSCFSet addObject:] ()
#7 0x348cb70c in -[UINib instantiateWithOwner:options:] ()
#8 0x348cce08 in -[NSBundle(UINSBundleAdditions) loadNibNamed:owner:options:] ()
#9 0x348465e8 in -[UIViewController _loadViewFromNibNamed:bundle:] ()
#10 0x34813fa4 in -[UIViewController loadView] ()
#11 0x346f8ebe in -[UIViewController view] ()
【问题讨论】:
你能在你使用视图控制器的地方显示代码吗? 【参考方案1】:假设rvc
是一个保留属性,你有一个泄漏。这就是控制器没有得到dealloc
ated 的原因。当您创建视图控制器时,您会过度保留它:
self.rvc = [[RootViewController alloc] initWithNibName:...];
alloc
返回一个保留对象 (+1)。然后,属性设置器也保留对象 (+2)。稍后,当您释放 (-1) 对象时,您会得到 +1。
要解决此问题,请使用临时变量或autorelease
:
self.rvc = [[[RootViewController alloc] initWithNibName:...] autorelease];
另一个问题是您释放属性所持有的对象的方式:
[self.rvc release];
在此声明之后,您已经放弃了对象的所有权,并且没有任何东西可以保证该对象在将来仍然有效,但您的属性仍然持有指向它的指针。换句话说,你有一个潜在的悬空参考。所以,当你用这个单一的语句释放它时,将属性 nil (这将释放旧对象):
self.rvc = nil;
【讨论】:
谢谢。那么......我应该重命名我的问题吗? :D 不客气。我认为您不应该重命名您的问题,因为它反映了您最初的想法。【参考方案2】:将[self.rvc release];
更改为[rvc release];
:
- (void)setCurrentCourse:(Course *)newCourse
// area of concern
if (currentCourse == nil)
[self.rvc.view removeFromSuperview];
[rvc release];
// HERE I want rvc to be deallocated, but the retainCount is one.
else
// This is where I allocate the rvc instance
rvc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:[NSBundle mainBundle] courseSelectionController:self];
[self.view addSubview:self.rvc.view];
或使用self.rvc = nil;
,因为当您将 nil 设置为实例变量时,setter 只会保留 nil(什么都不做)并释放旧值。
并使用
rvc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:[NSBundle mainBundle] courseSelectionController:self];
而不是
self.rvc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:[NSBundle mainBundle] courseSelectionController:self];
【讨论】:
感谢您的回答。我的问题仍然存在。[self.rvc release]
有什么问题?
尝试将self.rvc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:[NSBundle mainBundle] courseSelectionController:self];
也更改为rvc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:[NSBundle mainBundle] courseSelectionController:self];
。
自我。调用自动生成的设置器代码,该代码保留传递的任何内容,因此分配某些内容,然后将其发送到 self.property 使其保留计数为 2,而不是您想要的 1。有关更详细的解释,请参阅 albertamg 的答案。以上是关于Nib 创建的视图保留文件的所有者防止 UIViewController 的释放的主要内容,如果未能解决你的问题,请参考以下文章