How do I restrict orientation per view controller

2020-02-10 06:43发布

问题:

My app is a UITabBarController --> UINavigationController --> UITableViewController --> UIViewController.

I want to do 2 things:

  1. Prevent my tableview from rotating, I want it to always stay portrait.

  2. FORCE & Allow my UIViewcontroller to rotate landscapeleft.

What I know:

  1. I understand that the viewcontroller at the top of the hierarchy controls rotation. This would be my UITabBarController? Or rather its only viewcontroller which would be at objectIndex:0?

  2. My project settings allow for Portrait, LL and LR rotations. Im thinking this is the pattern I need to follow in order to solve this is allow ALL at the top level to rotate and then control each vc individually, correct?

This is what I have found so far in SO.

So for my top hierarchy, i set the project settings to allow rotation to Portrait, LL and LR.

and then in my tableviewcontroller which i dont want to rotate:

-(BOOL)shouldAutorotate{
    return NO;
}

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

and finally in my uiviewcontroller which I want to rotate:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskAllButUpsideDown;
}

-(BOOL)shouldAutorotate{
    return YES;
}

However this does not work. I can rotate both in any direction. I also dont know how to force rotation LL when I get to my uivc which is called from a modal segue from my tablevc.

Any help understanding this mess would be greatly appreciated :)

回答1:

Simple but it work very fine. IOS 7.1 and 8

AppDelegate.h

@property () BOOL restrictRotation;

AppDelegate.m

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
    return UIInterfaceOrientationMaskPortrait;
else
    return UIInterfaceOrientationMaskAll;
}

ViewController

-(void) restrictRotation:(BOOL) restriction
{
    AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    appDelegate.restrictRotation = restriction;
}

viewDidLoad

[self restrictRotation:YES]; or NO


回答2:

Ok, here it is. kinda complicated.

Project Settings must allow P, LL & LR

Storyboard is a UINavController with a UITableViewController with a push bar button segue to a UIViewController.

All scenes in storyboard must have inferred as orientation in simulated metrics. Just saying, cause after a while i had them all with different settings after testing so much.

Must have a Class for NavController, TableViewController and the given UIVController. My app started out as Single view, then I dragged in a UITVC and finally embedded the UITVC in a UINVC. Then I connected the UIVC to the UITVC bar button item I dragged in via push segue.

Set apps window.rootvc to the navVC, your top hierarchy vc (don't forget to set that ID in storyboards or it'll crash of course):

    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
    UINavigationController *myNavC = (UINavigationController*)[mainStoryboard instantiateViewControllerWithIdentifier:@"MainNav"];
    self.window.rootViewController = myNavC;

Tell big boss UINVC everyone can rotate:

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

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

Restrict tablevc so it won't rotate:

    - (BOOL)shouldAutorotate { return NO; }

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
        return (UIInterfaceOrientationMaskPortrait); 
    }

Allow last UIVC to rotate:

    - (BOOL)shouldAutorotate { return YES; }

    - (UIInterfaceOrientationMask)supportedInterfaceOrientations {
        return (UIInterfaceOrientationMaskAllButUpsideDown);    
    }


回答3:

Responce

It should not be confused UIDeviceOrientation and interface orientation here is my solution

Appdelegate.h

@property () UIInterfaceOrientationMask restrictRotation;

AppDelegate.m

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
     UIInterfaceOrientationMask restrictionOrientation = 0;

if (_restrictRotation == 0)
    return UIInterfaceOrientationMaskAll;

UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation];

switch (currentOrientation)
{
    case UIDeviceOrientationPortrait:

        if (!(UIInterfaceOrientationMaskPortrait & _restrictRotation))
            restrictionOrientation = UIInterfaceOrientationMaskAll;
        else
            restrictionOrientation = UIInterfaceOrientationMaskPortrait;

        break;

    case UIDeviceOrientationPortraitUpsideDown:

        if (!(UIInterfaceOrientationMaskPortraitUpsideDown & _restrictRotation))
            restrictionOrientation = UIInterfaceOrientationMaskAll;
        else
            restrictionOrientation = UIInterfaceOrientationMaskPortrait;

        break;

    case UIDeviceOrientationLandscapeLeft:

        if (!(UIInterfaceOrientationMaskLandscapeLeft & _restrictRotation))
            restrictionOrientation = UIInterfaceOrientationMaskAll;
        else
            restrictionOrientation = UIInterfaceOrientationMaskPortrait;

        break;

    case UIDeviceOrientationLandscapeRight:

        if (!(UIInterfaceOrientationMaskLandscapeRight & _restrictRotation))
            restrictionOrientation = UIInterfaceOrientationMaskAll;
        else
            restrictionOrientation = UIInterfaceOrientationMaskPortrait;

        break;

    case UIDeviceOrientationUnknown:

        if (!(UIInterfaceOrientationUnknown & _restrictRotation))
            restrictionOrientation = UIInterfaceOrientationMaskAll;
        else
            restrictionOrientation = UIInterfaceOrientationMaskPortrait;

        break;

    default:

        NSLog(@"Unknown orientation");

        break;
}

return restrictionOrientation;

}

In each vc add the function

-(void) restrictRotation:(UIInterfaceOrientationMask) restriction
{
    AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
    appDelegate.restrictRotation = restriction;

}

viewDidAppear

//
// Set vc orientation
//

[self restrictRotation:UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight];
 or what you want.

[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:   UIInterfaceOrientationPortrait] forKey:@"orientation"];

or what you want.