Aleksandar • Vacić

iOS bits and pieces

Allow landscape in portrait-only iPhone app, in iOS 7

While working on Banca 4.1, I needed to allow landscape orientation for the demo video, while still keeping the rest of the app portraint-only. I knew that iOS 7 has changed the way orientation is handled and after some searching and trying few tricks, I compiled the solution.

It’s suprisingly easy.

The key is this method, which you need to add in your AppDelegate file:

1
2
- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window

This is called each time a view controller (of any sort) is to be presented. They only key is to figure out the view hierarchy below the window and return UIInterfaceOrientationMaskAllButUpsideDown for that case.

My demo video is being shown as modal view controller, specifically MPMoviePlayerViewController. However, to complicate the things, it’s being presented from view controller which is contained in navigation controller which is also modally presented. Sounds like quite a mess, but nothing unusual, really – in Banca 4.1 the sequence is two taps only: you tap on “Support” at the bottom right, then tap on “Watch demo video”.

Thus the trick is to hunt through the hierarchy and find where the MPMoviePlayerViewController is. Sort-of general solution might be like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window {
  
  if ([[self.window.rootViewController presentedViewController]
              isKindOfClass:[MPMoviePlayerViewController class]]) {
      return UIInterfaceOrientationMaskAllButUpsideDown;
  } else {
      
      if ([[self.window.rootViewController presentedViewController]
                      isKindOfClass:[UINavigationController class]]) {

          // look for it inside UINavigationController
          UINavigationController *nc = (UINavigationController *)[self.window.rootViewController presentedViewController];

          // is at the top?
          if ([nc.topViewController isKindOfClass:[MPMoviePlayerViewController class]]) {
              return UIInterfaceOrientationMaskAllButUpsideDown;

          // or it's presented from the top?
          } else if ([[nc.topViewController presentedViewController]
                  isKindOfClass:[MPMoviePlayerViewController class]]) {
              return UIInterfaceOrientationMaskAllButUpsideDown;
          }
      }
  }
  
  return UIInterfaceOrientationMaskPortrait;
}

Fairly easy.