I'm trying to update my app for iOS 6, and the main challenge is handling autorotation. There are questions and search results that relate to this topic, but none that answer my question directly. I understand the deprecation of shouldAutorotateToInterfaceOrientation:
and its replacement with supportedInterfaceOrientations
and shouldAutorotate
- this question doesn't directly concern those.
Instead I'm interested in knowing how I can replace willAutorotateToInterfaceOrientation:duration:
, which is where my app handles almost all of its rotation animation and layout restructuring. My main view controller controls a full-screen view that is added to the main window on launch and which deals with the entire internal layout of the app, which is somewhat complicated. The willAutorotateToInterfaceOrientation:duration:
method in this view controller resizes some subviews directly and calls through to C++ objects that handle other subviews. Because of the variable nature of the interface, which includes a complex hierarchy of subviews, some that do not resize, some that are offscreen, and so on, I do not think Apple's autoresizing masks offer a powerful enough solution to handle this sort of autorotation.
Is there some way to take action in the same way that I do in willAutorotateToInterfaceOrientation:duration:
now? As I've found online and by experimentation, this method and didRotateFromInterfaceOrientation:
are never called in my main view controller in iOS 6. I've also found that viewWillLayoutSubviews
is never called, although I suspect that it wouldn't quite meet my needs anyway.
Please let me know if you need any further information. I hope there is a fairly straightforward solution to this and this is not an example of Apple abandoning developers to the wolves if they don't conform to a new, narrower protocol.
Edit: In case this helps to clarify, here's a basic shell of the functionality I'm talking about:
In AppDelegate.mm:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window makeKeyAndVisible];
MainViewController* mainViewController= [[MainViewController alloc] initWithNibName:nibName bundle:[NSBundle mainBundle]];
[self.window addSubview:mainViewController.view];
return YES;
}
In MainViewController.mm:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[UIView beginAnimations:NULL context:nil];
[UIView setAnimationDuration:duration];
[someViewController someMethod];
[someView setFrame:someRect];
[UIView commitAnimations];
someObject->CustomRotationFunction( toInterfaceOrientation, duration );
}
Generally speaking, assume the worst about what goes on in these functions and methods, e.g. someObject
owns views which change their frames, it owns other objects which own views which change their frames, etc.
Your main problem is that you're just adding your ViewController's view to the window instead of setting it as the rootViewController. That's the reason why the willRotateToInterfaceOrientation, didRotateToInterfaceOrientation and so on are never called in iOS6.
In iOS5, the shouldAutorotateToInterfaceOrientation was passed to every childViewController of the ViewController that was on the window which could then return whether or not you wanted to rotate. In iOS6, the rootViewController decides whether or not your application supports a certain orientation. So you NEED to set a rootViewController in iOS6 and it is best practice to do so in earlier iOS versions as well. The methods you need will then be called at the correct times and will be passed to any childViewControllers.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window makeKeyAndVisible];
MainViewController* mainViewController= [[MainViewController alloc] initWithNibName:nibName bundle:[NSBundle mainBundle]];
self.window.rootViewController = mainViewController;
return YES;
}