Why does rotation of iPhone cause crash when _existingView message is sent to deallocated object?
I have two view controllers: MyParentViewController
and MyChildViewController
.
The application starts with MyParent
. I push the MyChild
controller to the top of the navigation stack,开发者_StackOverflow中文版 so that the chain is like so:
MyParent
> MyChild
I log the object ID of MyChild
with NSLog(@"%p", self)
:
2009-11-20 05:08:29.305 MyApp[2213:207] MyChildViewController instance: 0x36afc20
When I press the back button from MyChild
this pops MyChild
off the stack and returns me to MyParent
.
When I rotate the iPhone while viewing MyParent
, my application crashes with the following error message:
2009-11-20 05:08:37.671 MyApp[2213:207] *** -[MyChildViewController _existingView]: message sent to deallocated instance 0x36afc20
I have no _existingView
method or instance variable in MyChildViewController
.
If I pop MyChild
off the stack, I think the navigation controller will release it, and I presume that it would be set to nil
, and that any messages sent to it would be ignored. Though that's not happening here, obviously.
Does anyone have any ideas why my application crashes on rotation?
Is there a way to find out what is sending the _existingView
message to MyChild
?
EDIT
Here's the code for pushing MyChild
on the stack:
MyChildViewController *_myChildViewController = [[MyChildViewController alloc] initWithNibName:@"MyChildViewController" bundle:nil];
_myChildViewController.managedObjectContext = self.managedObjectContext;
_myChildViewController.title = [_xyz name];
[self.navigationController pushViewController:_myChildViewController animated:YES];
UIBarButtonItem *_backButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"MyChildViewBackBarButtonItemTitle", @"") style:UIBarButtonItemStyleDone target:nil action:nil];
self.navigationItem.backBarButtonItem = _backButton;
[_backButton release];
[_myChildViewController release];
EDIT 2
I think I may have solved this. I have an UISearchDisplayController
added to the view controller nib via Interface Builder.
Originally, I set this to nil
when the MyChild
controller is sent -viewDidUnload
, thinking it is usually enough to set IBOutlet
instances to nil in this method. But this doesn't appear to be enough for my search display controller. When I release this in -dealloc
I don't get the crash. Is this a bug, I wonder, or expected behavior?
There is a way to find out more about who called (found here):
[...] Also, by the time the app is terminated due to the uncaught exception there is no useful backtrace. If you set a breakpoint on objc_exception_throw the debugger will break before the exception is thrown and you'll have a useful backtrace. I do this with a .gdbinit file. Create a file named .gdbinit and place it in your home directory. This is the contents of mine:
- fb -[NSException raise]
- fb -[_NSZombie release]
- fb szone_error
- fb objc_exception_throw
It's also possible to set these kinds of breakpoints in the Xcode breakpoints window or in the debugger console. [...]
But I assume that won't fix your problem... _existingView seems to be called by the framework when rotating the phone. The only line I can think of telling the framework to perform this on _myChildController is this one:
myChildViewController.managedObjectContext = self.managedObjectContext;
Doesn't it work without this?
_existingView
is an internal variable of an UIViewController instance, defined in UIViewController.h
Maybe you are retaining your MyChildViewController
someplace in your code.
I was struggling with this too, and the solution was similar to Alex Reynolds'. I release my UISearchDisplayController on -dealloc method, but it had to be before the [super dealloc]. If I release it after super deallocation, it still crashes.
精彩评论