iOS 6 and Rotation

The iOS 6 API introduces a new way to handle device rotation. The approach used in all previous APIs has been deprecated. What seems like a small change to the name of a method is actually a lot more problematic once you start to dig in and refactor your code for iOS 6.

While I didn't have as much trouble dealing with this as some developers I did lose a lot of time this week trying to figure out how to best adapt to the new model of handling rotation.

Here's a quick run-down of what I learned.

  • You need to define all of the orientations your app could possibly support at the application level. This means clicking on the appropriate orientations in "Supported Interface Orientations" found under your project settings -> targets -> summary or implementing the method application:supportedInterfaceOrientationsForWindow: in your app delegate. If you choose to implement the delegate method you will need to return the appropriate UIInterfaceOrientationMask combination for your application. You can find the possible mask values defined in UIApplication.h.
  • Once you've defined the global rotation options for your application you can then set the orientations that are supported by each view controller in your application. Apple has deprecated shouldAutorotateToInterfaceOrientation: and now requires you to override supportedInterfaceOrientations: in each of your view controllers that need to handle rotation. This method is similar to the app delegate method in that it needs to return the appropriate UIInterfaceOrientationMask combination for supported orientations. supportedInterfaceOrientations: is only called if shouldAutorotate returns YES.
  • When a view controller returns an orientation from supportedInterfaceOrientations: that value is compared to those values defined at the application level. If the value returned by the view controller is one of the application's supported orientations the device will rotate, otherwise it will not.
  • The only view controller that can cause the application to rotate is the top-most view controller. This is a huge change. You can no longer have child view controllers dictate to the application that a given view should rotate. This is especially tricky if your top-most view is a UINavigationController since it will ALWAYS be the top-most view. In the one application I maintain I wanted my app to support rotation in all supported iPhone directions but the only view controllers I wanted to rotate in all directions were modal view controllers (photo galleries, text editing, and web views). I didn't want the views being managed by the UINavigationController to rotate. To fix this I simply created my own subclass of UINavigationController and overrode the supportedInterfaceOrientations: method to only return the up orientation for those views on the UINavigationController's stack.
  • If your view controller still implements shouldAutorotateToInterfaceOrientation: iOS will convert the values it returns to the appropriate UIInterfaceOrientationMask values. This allows you to support iOS 6 as well as older iOS devices.

I set aside a lot of time this week to deal with issues related to the larger screen of the iPhone 5 and never once gave a thought to rotation...until I rotated my phone and nothing happened. In all honesty, I found layout issues related to the new larger screen to be the easiest issues to resolve. Refactoring to support Apple's new model of rotation was an unexpected challenge.