How do I remove a no longer needed view controller?
I am using my app delegate to transition between view controllers. When the delegate decides it no longer needs the view controller, based on messages from the server, it needs to remove the current view and replace it with another one. Currently my code looks like the following:
- (void) showFight: (NSNotification*) notification
{
if(self.window.rootViewController != self.fightViewController)
{
NSDictionary* dict = [notification userInfo];
FightViewController *fightView = [[FightViewController alloc]
initWithNibName:@"FightViewController" bundle:nil];
fightView.userId = _userId;
self.fightViewController = fightView;
[fightView release];
[self.radarViewController.view removeFromSuperview]; // Doesn't work.
self.window.rootViewController = self.fightViewController;
[self.fightViewController showMonster:dict];
}
}
I know my view 开发者_开发技巧controller isn't being removed because I can hear sound effects from it in the background.
I want to completely destroy the view controller, as I only want one view controller in memory at any time. I plan to create the view controller each time from scratch, as shown in the code above. Am I doing this improperly?
The problem here seems to be that you are not releasing the view controller. Think about what actually happens in your code at:
[self.radarViewController.view removeFromSuperview];
You remove the view from its super view. The view controller still exists, and what it does is control what should be shown on the view, and in your case apparently playing sound.
Put in an easy way: The view controller is an object. It has a child, the view. That's another object. You remove the view from another view, but the object controlling the removed view still lives (and actually, so does the view object).
If you want to kill the entire view controller, call this after removing the view from its superview:
[self.radarViewController release];
Or, if the view is a retain property (which i assume by looking at your code) you can also use:
self.radarViewContoller = nil;
which automatically releases for you in the synthesized setter.
When the view controller is released, its reference count is subtracted by one. If the reference count reaches zero, then the controller will be deallocated.
So far I understand your problem is to add the new ViewController on server notify and change the current view with new View. First of all you've to add the view controller just like below because the reference won't help to update the view.
[self.window.rootViewController.view addSubview: self.fightViewController.view]
In my opinion you need to tag your Controllers and check before adding the controller that if it's already exist in the memory, otherwise the pool of object will leak. Just Say No to Memory Leaks!!
- (void) showFight: (NSNotification*) notification
{
UIView *fightView = (UIView *)[self.window.rootViewController.view viewWithTag: FIGHT_VIEW_TAG];
if (self.window.rootViewController.view.tag != fightView.tag) {
NSDictionary* dict = [notification userInfo];
FightViewController *fightView = [[FightViewController alloc]
initWithNibName:@"FightViewController" bundle:[NSBundle mainBundle]];
//Remove the current view.
[self.window.rootViewController.view removeFromSuperview]; // If you're adding the fighting View in the root View, then why are you trying to remove current view through radar controller which has already added in the window (root view).
fightView.userId = _userId;
[fightView setTag: FIGHT_VIEW_TAG];
[self.window.rootViewController.view addSubView: self.fightViewController.view];
[self.fightViewController showMonster:dict];
[fightView release];
}
}
You don't need to take them as global until your requirements are different.
精彩评论