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 dealloc
ated. 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];
精彩评论