views:

162

answers:

2

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, 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?

A: 

_existingView is an internal variable of an UIViewController instance, defined in UIViewController.h
Maybe you are retaining your MyChildViewController someplace in your code.

luvieere
I figured as much. Do you know what is sending this message?
Alex Reynolds
As far as I know, I am not actively retaining `MyChildViewController`. It is released immediately after the navigation controller takes ownership.
Alex Reynolds
+1  A: 

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?

Kai