开发者

Nib-created view retaining file's owner prevents deallocation of UIViewController

I have a view controller that I want to be released (and then possibly reallocated later in the application). The problem is that its view se开发者_运维百科ems to hold a strong reference to it as shown in the stack trace below. Does the view need to be deallocated before the view controller? If so, how can I do this? Thanks for the help :)

Code:

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


Assuming rvc is a retain property, you have a leak. That's why the controller is not getting deallocated. When you create the view controller you are over-retaining it:

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

alloc returns a retained object (+1). Then, the property setter also retains the object (+2). Later, when you release (-1) the object, you end up with a +1.

To solve this, either use a temporary variable or autorelease:

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

Another concern is the way you release the object that your property is holding to:

[self.rvc release];

After this statement, you have relinquished ownership of the object and nothing guarantees you that the object will be valid in the future but your property is still holding a pointer to it. In other words, you have a potential dangling reference. So, nil out the property as you release it with this single statement (this will release the old object):

self.rvc = nil;


Change [self.rvc release]; to [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];
    }
}

or use self.rvc = nil; because when you set nil as an instance variable, the setter just retains nil (which does nothing) and releases the old value.

And use

rvc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:[NSBundle mainBundle] courseSelectionController:self];

instead of

self.rvc = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:[NSBundle mainBundle] courseSelectionController:self];

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜