How do I remove a no longer needed view controller?

George Johnston picture George Johnston · Apr 28, 2011 · Viewed 9.2k times · Source

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?

Answer

Accatyyc picture Accatyyc · Apr 28, 2011

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.