Hi, I'm Hwee-Boon Yar

I write, ship and sell software products. iOS/OS X app developer based in Singapore, working remotely. This is my blog.

.

Need to run a code review on your codebase? Hire me

I've seen people asking how to support different device orientations within the same iOS app, especially since iOS 6 introduced some changes to how device orientation is handled and with the growing popularity of RubyMotion, there is a new breed of developers. It's really straightforward when the entire app supports the same set of orientation(s). But it gets a little confusing when you want different screens to support different orientations.

Here's some sample code for how to do it correctly in RubyMotion. Developers using Objective C should be able to adapt this too.

In Rakefile (for ObjC developers, do something similar in your info.plist file), set the following to indicate all the orientations supported by the app. If you have a screen in your app that plays video and you want to allow the user to also play it in landscape, you need to include both portrait and landscape orientations here even if the rest of the app is always in portrait.

app.interface_orientations =
    [:portrait, :landscape_left, :landscape_right]

The rest of it is code. If you use UINavigationControllers anywhere in your app, you will want to use your own subclass instead:

class AppDelegate
  def application(application,
        didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    @window.rootViewController =
        NavigationController.alloc.initWithRootViewController(
            PortraitViewController.alloc.init)
    @window.makeKeyAndVisible
    true
  end
end

The custom UINavigationController just forwards the relevant calls to it's topmost view controller:

class NavigationController < UINavigationController
  #####Orientation

  def shouldAutorotate
    topViewController.shouldAutorotate
  end

  def supportedInterfaceOrientations
    topViewController.supportedInterfaceOrientations
  end

  def preferredInterfaceOrientationForPresentation
    topViewController.preferredInterfaceOrientationForPresentation
  end

  def shouldAutorotateToInterfaceOrientation(interfaceOrientation) {
    topViewController.shouldAutorotateToInterfaceOrientation(
        interfaceOrientation)
  end
end

Here's how to implement a UIViewController subclass that only supports portrait orientation:

class PortraitViewController < UIViewController
  def initWithNibName(nibName, bundle:nibBundle)
    super(nibName, nibBundle)

    self.view.backgroundColor = UIColor.blueColor
    b = UIButton.buttonWithType(UIButtonTypeRoundedRect)
    b.frame = [[60, 100], [200, 20]]
    b.setTitle('Show VC that rotates', forState:UIControlStateNormal)
    b.addTarget(self, action:'click',
        forControlEvents:UIControlEventTouchUpInside)
    view.addSubview(b)
    self
  end

  def click
    vc = PortraitAndLandscapeViewController.new
    navigationController.pushViewController(vc, animated:true)
  end

  #####Orientation

  def shouldAutorotate
    true
  end

  def supportedInterfaceOrientations
    UIInterfaceOrientationMaskPortrait
  end

  def shouldAutorotateToInterfaceOrientation(interfaceOrientation)
    interfaceOrientation == UIInterfaceOrientationPortrait
  end

  #Optional depending on your app
  def preferredInterfaceOrientationForPresentation
    UIInterfaceOrientationPortrait
  end
end

Here's how to implement a UIViewController subclass that supports both portrait and landscape orientations:

class PortraitAndLandscapeViewController < UIViewController
  def initWithNibName(nibName, bundle:nibBundle)
    super(nibName, nibBundle)
    self.view.backgroundColor = UIColor.greenColor

    self
  end

  #####Orientation

  def shouldAutorotate
    true
  end

  def supportedInterfaceOrientations
    UIInterfaceOrientationMaskAllButUpsideDown
  end

  def shouldAutorotateToInterfaceOrientation(interfaceOrientation)
    interfaceOrientation == UIInterfaceOrientationPortrait ||
    interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
    interfaceOrientation == UIInterfaceOrientationLandscapeRight
  end

  #Optional depending on your app
  def preferredInterfaceOrientationForPresentation
    UIInterfaceOrientationPortrait
  end
end

Like this post? Follow me @hboon on Twitter.