Nib 创建的视图保留文件的所有者可防止 UIViewController 的释放



我有一个视图控制器,我想要释放(然后可能在应用程序稍后重新分配)。问题是,它的视图似乎持有对它的强引用,如下面的堆栈跟踪所示。视图需要在视图控制器之前被释放吗?如果有,我该怎么做?谢谢你的帮助:)

代码:

- (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];

最新更新