0

I Currently have a nearly landscape only iPad application on the app store and have been having some issues with the new iOS 6 way on handling rotation locking.

It is a UINavigationController based application and since iOS handles most the responsibility to the rootViewController of the UIWindow I have to manually ask each UIViewController what rotation it wants.

As I have a very large amount of UIViewControllers manually adding code to each Controller to do this would have taken me ages, So I made an extension of both the UINavigationController and UIViewController to override these calls and there I could manually set what views I want to block Portrait to and what ones to allow it to.

UINavigationController-Extension.m:

//
//  UINavigationController-Extension.m
//  DrivingInstructor
//
//  Created by Liam Nichols on 06/12/2012.
//  Copyright (c) 2012 Liam Nichols. All rights reserved.
//

#import "UINavigationController-Extension.h"


@implementation UINavigationController (Extension)

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return [self.topViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

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

-(BOOL)shouldAutorotate
{
    return YES;
}

@end


@implementation UIViewController (Extension)

-(BOOL)shouldAutorotate
{
    return NO;
}

-(NSUInteger)supportedInterfaceOrientations
{
    if ([[self portraitClasses] containsObject:NSStringFromClass([self class])])
    {
        return UIInterfaceOrientationMaskAll;
    }
    return UIInterfaceOrientationMaskLandscape;
}

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    if ([[self portraitClasses] containsObject:NSStringFromClass([self class])])
    {
        return YES;
    }
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

-(NSArray*)portraitClasses
{
    static NSArray *classes;
    if (classes == nil)
    {
        classes = @[ @"MockTestController", @"PLUILibraryViewController", @"PhotoViewController" ];
    }
    return classes;
}

@end

At fist I thought this had fixed the issue (I also kept the app locked to landscape in the info.plist so that it would launch to lanscape and then in the app delegate I called application:supportedInterfaceOrientationsForWindow: and returned all orientations so that my select views could access portrait if needed.

So this seemed to have worked and all view controllers where locked to lanscape accept the 3 I specified in my extension class.. I was monitoring the extension and whenever I pushed to the new controller it checked for the orientations and locked the app to the specified orientation.

The one issue I found however and can't seem to fix is that when i for example am in portrait on my allowed view controller and try to pop back to the previous view controller what is locked to landscape, supportedInterfaceOrientations is never called again and the view that should be locked to landscape isn't (this causes issues).

As per apples documents, this is how it should work as the responsibility of handling rotation is passed to the rootViewController and as the user isn't rotating their device and the rootViewController isn't changing there is no need to request supportedInterfaceOrientations..

My question is, is there a way to get the application to force call supportedInterfaceOrientations or should I be doing this differently?

Thanks for reading, and If I can find a solution to this last bug then this code might be a good reference to people who are also in the same situation.

-----Edit-----

Was doing some further investigation and found that just before the viewWillAppear: function, supportedInterfaceOrientations is actually in fact called on the controller I am attempting to pop back to and does return the correct mask UIInterfaceOrientationMaskLandscape to try and make it automatically rotate back from portrait however it doesn't seem to listen to this response and still leaves the UIViewController in portrait...

So this means that I do not need to call the supportedInterfaceOrientations again but instead make the device rotate back round to landscape!

liamnichols
  • 12,419
  • 2
  • 43
  • 62

1 Answers1

0

According to the documentation you can call:

+ (void)attemptRotationToDeviceOrientation

which if I understand the documentation correctly then would query rotation to the different view controllers again.

David van Driessche
  • 6,602
  • 2
  • 28
  • 41
  • unfortunately that doesn't work as its usage is for example to try bring my landscape app round to portrait if I am holding it in portrait, thanks anyway – liamnichols Dec 12 '12 at 15:50