New operating systems offer many new features but with that we also receive depreciations that can cause developers to back track and fix new problems. In iOS 6 Apple depreciated the method shouldAutorotateToInterfaceOrientation. Apple also added some new functions and changed the way that you control view and window rotation.
Q: What problems does this cause?
A: Apps ran in iOS 6 will not autorotate.
I read Apple’s documentation on this issue (Depreciated UIViewController Methods, View Controller Guide for iOS) and read through dozens of partial solutions online but nowhere could I find a complete solution.
Here’s a complete solution that works.
1. Create a new view based application using the latest SDK (Xcode 4.5).
2. Create a navigation controller subclass. I named the navigation controller subclass CustomNavigationController.
// CustomNavigationController.h // autorotationfix #import @interface CustomNavigationController : UINavigationController @end
// CustomNavigationController.m // autorotationfix #import "CustomNavigationController.h" @interface CustomNavigationController () @end @implementation CustomNavigationController - (BOOL)shouldAutorotate { return self.topViewController.shouldAutorotate; } - (NSUInteger)supportedInterfaceOrientations { return self.topViewController.supportedInterfaceOrientations; } @end
3. Link the navigation controller to your app delegate.
#import "CustomNavigationController.h"
4. Customize the app delegate didFinishLaunchingWithOptions method to subclass your navigation controller.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // set initial view self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; navigationController = [[CustomNavigationController alloc] initWithRootViewController:viewController]; // iOS 6 autorotation fix [navigationController setNavigationBarHidden:YES animated:NO]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; [self.window setRootViewController:navigationController]; // iOS 6 autorotation fix //[self.window addSubview:navigationController.view]; [self.window makeKeyAndVisible]; return YES; }
5. Add the supportedInterfaceOrientationsForWindow method to the app delegate.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window // iOS 6 autorotation fix { return UIInterfaceOrientationMaskAll; }
6. Add new methods (shouldAutorotate, supportedInterfaceOrientations, preferredInterfaceOrientationForPresentation) to your individual view controllers to turn autorotation on and off and specify allowable rotations. Keep the shouldAutorotateToInterfaceOrientation method so the app rotation continues to work correctly on older iOS versions.
In this example I added some idiom logic for a Universal app so the iPhone will not rotate but the iPad will. By setting shouldAutorotate to YES if you push from this viewController to a second view controller, rotate the second view controller to landscape then pop the second view controller – the first view controller will auto rotate back to portrait. If shouldAutorotate is set to NO then the first view controller will not rotate back to portrait:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } - (BOOL)shouldAutorotate // iOS 6 autorotation fix { return YES; } - (NSUInteger)supportedInterfaceOrientations // iOS 6 autorotation fix { if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { return UIInterfaceOrientationMaskPortrait; } else { return UIInterfaceOrientationMaskAll; } } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation // iOS 6 autorotation fix { return UIInterfaceOrientationPortrait; }
In this example both the iPhone and iPad will rotate in all 4 directions:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } - (BOOL)shouldAutorotate // iOS 6 autorotation fix { return YES; } - (NSUInteger)supportedInterfaceOrientations // iOS 6 autorotation fix { return UIInterfaceOrientationMaskAll; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation // iOS 6 autorotation fix { return UIInterfaceOrientationPortrait; }
As you can see, this new setup allows you to add custom rotation settings to every view controller. For Universal apps, it also allows you to control allowable rotation for both the iPhone and iPad.
Download a sample solution: autorotationfix.zip
In this solution the first view controller will stay in portrait for all 4 rotations. The second view controller will rotate automatically for all 4 rotations. If you push to the second view controller, rotate to landscape, then tap the back button – the first view controller will stay in portrait.
Rotating the first view controller:
Rotating the second view controller:
Regards,
John DiSalvo
Lead Developer
DiSalvo Technologies, LLC.