4

just had to update an iOS 5 App to iOS 6 and of course stumbled over the interface orientation issues. I now already know that things changed and I even know what changed, still I can't seem to manage it on my own.

My App consists of several viewcontrollers, which get pushed onto a navigationcontroller. All viewcontrollers are supposed to be in landscape orientation, except for one, which should be in portrait orientation. In iOS 5 everything worked fine, but now the one controller in portrait mode is also shown in landscape mode and of course gets distorted.

My iOS 5 code looked like that:

Viewcontroller in landscape mode:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation==UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation==UIInterfaceOrientationLandscapeRight);
}

Viewcontroller in portrait mode:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation==UIInterfaceOrientationPortrait) || (interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown);
}

Now that I found out about the changes in iOS 6 I implemented

AppDelegate: (allowing all orientations, like in the plist)

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskLandscapeLeft|UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

Viewcontroller in landscape mode: (restricting orientations to landscape mode)

- (NSUInteger) supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight
}

-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

- (BOOL)shouldAutorotate{ 
return YES;
}  

Viewcontroller in portrait mode: (restricting orientations to portrait mode)

- (NSUInteger) supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { 
return UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown;
}

- (BOOL)shouldAutorotate { 
return YES;
}

From my understanding this should work, but the truth is it works even less than before. First, the landscape mode viewcontrollers don't stay in landscape mode, they rotate freely in all directions, this is of course not what I wanted. Second, the viewcontroller in portrait mode will crash with

Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'preferredInterfaceOrientationForPresentation must return a supported interface orientation!'

After some trial and error I only seem able to lock all controllers to landscape mode, via the plist file/appdelegate, which of course forces the portrait mode controller also into landscape mode. On the other hand I can manage to have the portrait mode controller in proper orientation, but this will also rotate the landscape mode controllers into portrait mode. I can't seem to get both to work.

Any ideas?

El Duderino
  • 855
  • 1
  • 10
  • 21

2 Answers2

7

Ok I fixed it.

I made a category for UINavigationController

@implementation UINavigationController (Rotation_IOS6)

-(BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}

@end

to forward the values of the view controllers to the navigationcontroller...

I also had to replace presentModalViewController with presentViewController as the first one is deprecated now.

btw, yes there as a typo in my appdelegate...this is correct.

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskLandscapeLeft|UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown;
}
El Duderino
  • 855
  • 1
  • 10
  • 21
  • 2
    Categories are made to **add new methods**, not **overriding** existing ones. – Marcelo Apr 14 '13 at 01:40
  • 1
    This fails when the top view controller does not implement the new orientation methods, e.g. if the top VC is some Apple built-in VC (specifically the choose-photo VC of ABPersonViewController). To fix that, check the value returned from the top VC: `UIInterfaceOrientationMask topMask = [self.topViewController supportedInterfaceOrientations]; return topMask ? topMask : UIInterfaceOrientationMaskAllButUpsideDown;` – Yonat Jul 29 '13 at 05:02
0

Just observed that in your UIInterfaceOrientationMaskLandscapeLeft written twice in appdelegate LandscapeRight missing If its just typo and still facing problem after correction

I found only rootViewControllers - (BOOL)shouldAutorotate; get called. Here ur rootViewController is NavigationController. And for pushed viewController this is not getting called so u hav to decide orientation support for pushed view from navControllers methods only. Following worked for me for my navControllers pushed viewController
Override UINavigationControllers methods

- (BOOL)shouldAutorotate;
- (NSUInteger) supportedInterfaceOrientations;

Code will be something like this for u

@implementaion UINavigationController(Rotation)

- (BOOL)shouldAutorotate
{
return YES;
}

- (NSUInteger) supportedInterfaceOrientations
{
    NSArray *viewsArray = [self viewController]//stack of pushed controller

    NSUInteger orientationToReturn = assignAllMask;

    for(UIViewController *temp in  viewsArray)
    {
        if([temp isKindOfClass:MyOnlyLandscapeViewController] == YES )
        {
            orientationToReturn = assignLandscapeMask;
            break;
        }
        else if([temp isKindOfClass:MyOnlyPortraitViewController] == YES )
        {
            orientationToReturn = assignPortraitMask;
            break;
        }
    }

    return orientationToReturn;
}

@end
Aditya Deshmane
  • 4,676
  • 2
  • 29
  • 35
  • Thx for the effort, but I already fixed it (after some more trial and error). I think it also had something to do with the deprecated modal view controller functions. See my answer. – El Duderino Oct 11 '12 at 10:44