Nib创建的视图保留文件的所有者阻止了UIViewController的重新分配

时间:2011-10-11 23:14:20

标签: objective-c ios cocoa-touch uiviewcontroller nib

我有一个我想要发布的视图控制器(然后可能会在应用程序中重新分配)。问题是它的视图似乎对它有强烈的引用,如下面的堆栈跟踪所示。是否需要在视图控制器之前取消分配视图?如果是这样,我该怎么做?谢谢你的帮助:)

代码:

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

假设rvc是保留属性,您有泄漏。这就是控制器未获得dealloc的原因。创建视图控制器时,您过度保留

self.rvc = [[RootViewController alloc] initWithNibName:...];

alloc返回一个保留对象(+1)。然后,属性设置器还保留对象(+2)。稍后,当您释放(-1)对象时,最终会得到+1。

要解决此问题,请使用临时变量或autorelease

self.rvc = [[[RootViewController alloc] initWithNibName:...] autorelease];

另一个问题是您释放属性所持有的对象的方式:

[self.rvc release];

在此声明之后,您已放弃对象的所有权,并且没有任何保证您将来该对象有效但您的属性仍然保持指向它的指针。换句话说,你有一个潜在的悬挂参考。因此,当您使用此单个语句释放它时,nil out属性(这将释放旧对象):

self.rvc = nil;