我有一个视图控制器,我想要释放(然后可能在应用程序稍后重新分配)。问题是,它的视图似乎持有对它的强引用,如下面的堆栈跟踪所示。视图需要在视图控制器之前被释放吗?如果有,我该怎么做?谢谢你的帮助:)
代码:- (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];
}
}
Backtrace from overrides -(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] ()
假设rvc
是保留属性,您有泄漏。这就是为什么控制器没有得到dealloc
。当你创建视图控制器时你是过度保留它:
self.rvc = [[RootViewController alloc] initWithNibName:...];
alloc
返回一个保留对象(+1)。然后,属性设置器也保留对象(+2)。之后,当您释放(-1)对象时,您将得到一个+1。
要解决这个问题,可以使用临时变量或autorelease
:
self.rvc = [[[RootViewController alloc] initWithNibName:...] autorelease];
另一个问题是你释放你的属性所持有的对象的方式:
[self.rvc release];
在此语句之后,您已经放弃了对象的所有权,并且没有任何东西可以保证该对象在将来仍然有效,但是您的属性仍然持有指向它的指针。换句话说,你有一个潜在的悬空引用。因此,当你用这条语句释放属性时,将其空出来(这将释放旧对象):
self.rvc = nil;
将[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];