Preventing bad access crash for popViewControllerA

2019-06-06 07:37发布

问题:

So, under low memory, my root view is unloaded. That's expected and accounted for. However, how do I deal with modal/pushed view controllers who need to be popped, since they reference the main navigationController? I have a custom Done button in a pushed view controller, which calls [self.navigationController popViewControllerAnimated:YES]. If the root view has been unloaded, this gives a bad access error. Is there a better way to do this?

My setup is AppDelegate has a NavigationController this NavigationController has a view controller MainViewController

//MainViewController.m
- (IBAction)showAnotherController:(id)sender
{
    AnotherViewController *   anotherViewController;
    anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];

    [self.navigationController pushViewController:anotherViewController animated:YES];
    [anotherViewController release];
}

//...Here I can simulate a memory warning to force unloading of MainViewController's view

//in AnotherViewController.m, called from a custom toolbar item
- (IBAction)done:(id)sender
{
    [self.navigationController popViewControllerAnimated:YES]; // bad access here, looks like self.navigationController is no longer available. Am I doing this wrong?

}

回答1:

The scenario you're describing does not cause bad access. However, if you don't handle the described scenario carefully you get bad access. Since you haven't showed me any code I can't tell you that this is the problem you're having, but it's a very common problem.

When you receive a memory warning and your view is unloaded, you probably release a bunch of stuff. In addition to releasing the variables you also have to set them to nil. If you don't, you're facing the risk of sending messages to released objects, which causes bad access.

Again, I can't know that this is your problem, but it's usually the problem.

EDIT: Since you seem to believe that self.navigationController doesn't exist (it probably does) I'm gonna tell you about something called NSZombie:

NSZombie will tell you what released object is being sent a message (aka EXC_BAD_ACCESS). This is a very useful tool when you get EXC_BAD_ACCESS, so learn how to use it.

To activate NSZombie do the following:

  1. Get info of the executable.
  2. Go to the arguments tab.
  3. In the "Variables to be set in the environment:" section add:

Name: NSZombieEnabled Value: YES

Then run your app as usual and when it crashes it should tell you which deallocated object received the message.