I am not sure if something has changed in the iPhone SDK 3.0 but I am getting the strangest error. I have a view controller hierarchy where I switch between view controllers
Evidently, the controller is still registered for the notification in question. send -removeObserver:self to the notification center in your -dealloc method.
If anyone still cares, a simple solution is to create a root view controller + view that never changes.
Given SomeViewController + SomeView A, and SomeViewController + SomeView B, if you add view A to the window as a subview, then add view B as a subview and remove view A, the app will crash on rotate.
To prevent the crash, create a generic UIViewController + UIView X, and add view X to the window as a subview. Add and remove views A and B to/from view X, not the window directly. The app will no longer crash.
Note that it's not enough to just add a view to the window; you must add a view that has a view controller.
I have posted an answer here:
https://stackoverflow.com/a/19237139/539149
I had a place that said:
[viewController release];
viewController = NULL;
Which caused release to be called twice (so the memory was freed immediately) but the zombie wasn't revealed until an object owned by iOS tried to reference the object later in the main thread.
So after a week of waiting, Apple Developer Technical Support managed to help me sort my problem out. Here is their response:
"I've looked over your code and found a few things you need to be concerned about, some of which may contribute to your problem. In your
ControllerSwitchAppDelegate.m
source, you are implementing "didRotate
" method. It might be worth checking for device orientation notifications at the view controller level rather than at the UIApplication level. This will make your code much more simpler and encapsulated allowing each view controller that is shown to handle its own rotation logic. You are also using multiple view controllers at the same time, that being, both "view" properties are being added and remove when the device is rotated. This is not exactly the common approach in which to use the UIKit. The idea is to present one view controller (or its view property) at a time and not have a parent view controller swap in different sub-view controllers. Granted on the surface your approach seems doable, but in the long run, I recommend a different approach.We have a sample called "AlternateViews", which can be found at - http://developer.apple.com/iphone/library/samplecode/AlternateViews/index.html
In this sample, it pretty much does what you need. It provides an "alternate" view controller for a given device orientation. Is merely presents one view controller over another using "presentModalViewController" with a transition property called "modalTransitionStyle" which will give you a cross fade affect."
What I ended up doing was using a super view controller that presented and dismissed view controllers. Rather than swapping view controllers and removing sub views using the AppDelegate.
This is a good reason to set the ToolbarController = nil
after releasing it. It's safe to send messages to nil, but not to addresses of deallocated objects. In this case your sending a message to an address of an object that doesn't exit, which is causing a crash.
It's a waste of time to check for the ToolbarController != nil
before sending the message, because if it's nil, than you can send the message safely. if it is not nil and valid, then it will return YES or NO. But if it's a pointer to deallocated memory (such as you seem to have here) it's going to crash anyway.
I've run into this problem as well. The order of events is:
(1) create the application's single UIWindow object
(2) add a subview that's managed by a view controller to the window
(3) remove the first view and add a new one
If I rotate the device afterwards, the application crashes because of a message sent to the deallocated view controller. (Well, it's actually sending it to a sub-controller of the first view controller.) It's trying to send -[respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)].
If your application only runs in portrait mode, you can make the problem go away by adding a category to UIWindow that overrides _shouldAutorotateToInterfaceOrientation: to return NO for everything other than portrait mode.
Obviously, this isn't a real solution. I've double-triple-checked my code and I can find no reason why the window should be sending this message to the controller for a view that's been removed from the screen and deallocated. This problem also seems to have appeared in 3.0 and not before. Perhaps I'm doing something stupid, but there really seems to be something strange at work here.