So iOS6 has launched and many who have existing app in production which have the ability to autorotate will need to upgrade to iOS6 eventually and if they are like me they may run into issues when converting converting over to the new SDK.
What has changed
iOS asks the app whether or not it can autorotate and what are the supported orientations. These orientations are generally declared in your info.plist and for every viewController which you would like to allow to rotate you would simply override
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation and return YES or whatever specific orientations you wish to support. What is important is the current view controller is dictating whether or not the app rotates. In iOS6 this is reversed and the app determines whether or not an app can rotate by asking the navigation hierarchy in the reverse order. This happens by asking first the highest level on the navigation chain and whenever it gets the answer it needs it will use it. I will explain what I mean below.
The basics in code:
- (BOOL) shouldAutorotateToInterfaceOrientation: is now deprecated for iOS6 or later.
- (NSUInteger) application:supportedInterfaceOrientationsForWindow: is now put in the app delegate to declare the orientations for the window
- (BOOL) shouldAutorotate is now asked at the time of autorotation for a viewController or subclass
- (NSUInteger)supportedInterfaceOrientations is now used to return a mask representing the allowed orientations a viewController or subclass
Consider the example of an app with the navigation structure below:
Assume you wanted to allow autorotation for all views in your app.
iOS5 and older: You would traditionally override
shouldAutorotateToInterfaceOrientation in each of your viewControllers and return YES to allow autorotation for both.
iOS6: In iOS6 we now subclass the NavigationController override
- (NSUInteger)supportedInterfaceOrientations to return all orientations and override
- (BOOL) shouldAutorotate to return YES. this will return support for all orientations and the individual viewControllers will not be consulted.
Assume you wanted to allow orientation only for the second ViewController
iOS5 and older: You would override
shouldAutorotateToInterfaceOrientation in each viewController and return YES for the one which you allow autorotation and NO for the one you don’t.
iOS6: In this case you would still override the NavigationController but rather than returning YES for
shouldAutorotate you must consult your current ViewController. So you would override each viewController’s shouldAutorotate and return the appropriate value while in the NavigationController you would return your current viewControllers’s
return YES; // Or no
Your navigation controller
return self.topViewController.shouldAutorotate; //you are asking your current controller what it should do
What is important is to understand the basics of what is happening. For the above example the Navigation Controller is the parent and iOS always asks it what to do. If the entire app is allowed to autorotate or not you can simply return the answer at that level. If app contains views that will have different rules of autorotation then the navigation will have to ask the individual viewControllers for their result to be returned.
What does it all mean and my opinion
My opinion on this change is that its annoying to do the change over because I didn’t expect it but I welcome the change and I feel its a much more organized way of handling autorotation within your project structure while potentially making less code for you to write and maintain. The big thing that this improves is that you have to be very intentional when making an app that has specific rules of autorotation and the logic can be much easier to understand.
If you are having problems converting an existing project to iOS6 with autorotation ensure that you have these things covered:
- Ensure your .plist contains the proper supported orientations but this should be the case if coming from a previous project
- Ensure your app delegate overrides
application:supportedInterfaceOrientationsForWindow:and returns all supported orientations for your app
- within your
applicationDidFinishLaunchingWithOptionsfunction make sure you are setting your window’s rootViewController and not just adding its subview to the window
- Ensure you subclass all items in the Navigation hierarchy and override the new autorotation methods. This includes (tabBarControllers, NavigationControllers, ViewControllers, etc)
I hope this helps anyone who has to do a conversion to get through it and most importantly understand the new structure of autororation.
If you found this post helpful you can support me by buying my bodyweight workout app! (5 star average ratings, #1 in the ipad app health and fitness app store for 2 weeks straight…):