iOS 6 Orientation quirks and fixes for your iOS apps

Audio : Listen to This Blog.

From iOS 6 onwards the UI kit has minor changes on how the orientation can be supported in your iOS app. You will see lot of surprises in iPhone application development process when you compile a project which was working well on iOS 5 will not function on the latest iOS SDK 6.0. Recently we had to compile lots of client projects to support iOS 6, we were surprised that some of the apps where not working on Landscape orientation. This blog analyses the causes and suggests several fixes.

iOS Application Development

What are the causes?
1. No `rootViewController` set for the window in the app delegate class
It was a practice earlier that the view controller view would be added as a sub view to the UIWindow object. This is an easy fix:
Change you code from:
[self.window addSubview:aController.view];
to this code:
self.window.rootViewController = aController;
When UIKit receives an orientation notification, it uses the UIApplication object and the root view controller to determine whether the new orientation is allowed. If both objects agree that the new orientation is supported, then the user interface is rotated to the new orientation. Otherwise the device orientation is ignored.
So if in your app the rootViewController is nil, the orientation will be ignored. (For beginners: the root view controller provides the content view of the window.)
As additional information, in case `rootViewController == nil` the console will give the warning:
�Application windows are expected to have a root view controller at the end of application launch�
2. Deprecation of shouldAutorotateToInterfaceOrientation
For sure everyone is familiar with the code below:
– (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
We had to override this method in the view controller sub class and returns the BOOL based on the orientation requirements. Simple and familiar approach, isn�t it? But its deprecated in iOS 6 onwards.
So on iOS 6 onwards, as said already, a view controller that acts as the root view controller of the main window can declare what orientations it supports. It does this by overriding the supportedInterfaceOrientations method. By default, view controllers on devices that use the iPad idiom support all four orientations. On devices that use the iPhone idiom, all interface orientations but upside-down portrait are supported.
– (NSUInteger) supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft; //supported orientations } By returning the supported masks, yo can decide at runtime the required orientations. These are the possible values: typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) { UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait), UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft), UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight), UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown), UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown), UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), };
Also you need to make sure another method shouldAutorotate of UIViewController returns YES as shown below:
– (BOOL)shouldAutorotate{ return YES; }
This returns whether the view controller�s contents should auto rotate. Incase if you return it as NO, the �supportedInterfaceOrientations� method will never be called. By default auto rotation is supported, so incase you did not implement this method, still �supportedInterfaceOrientations� gets called.
To conclude: your Root View controller code should look something like this:
– (BOOL)shouldAutorotate{ return YES; //Returns YES if auto rotate required }
– (NSUInteger) supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft; //supported orientations }
Note: Prior to iOS 6, we used to decide the supported orientations on each and every UIViewController sub classes, but in iOS 6, its decided by the root view controller.
Two more important additions of apis in iOS 6:
– shouldAutomaticallyForwardRotationMethods:
For any custom code which you require upon rotation, we are doing it in either of the below callbacks of UIViewController class:
willRotateToInterfaceOrientation:duration: willAnimateRotationToInterfaceOrientation:duration: didRotateFromInterfaceOrientation: Note that these methods will never called incase you override �shouldAutomaticallyForwardRotationMethods� to NO in iOS 6.0. What this api does? This method returns a Boolean value indicating whether rotation methods are forwarded to child view controllers. This method is called to determine whether to automatically forward rotation-related containment callbacks to child view controllers. The default implementation returns YES. Subclasses of the UIViewController class that implement containment logic may override this method to control how these methods are forwarded. Hence if you override this method and return NO, you are responsible for forwarding the following methods to child view controllers. – shouldAutomaticallyForwardAppearanceMethods: Similar to the above, this method determines if the root view controller automatically forwards the appearance methods to its child view controllers or not. The default implementation returns YES. The following methods are having the impact: beginAppearanceTransition:animated: endAppearanceTransition Sample Code: Attached is some sample code which has the required methods discussed above. It doesn�t have any meaningful function, but has meaningful NSLogs, so check your console when running!

Read Similar Blogs