supportedInterfaceOrientations not working

2019-01-25 09:09发布

问题:

I want some of my ViewControllers landscape and some portrait so this is what I did:

I enabled landscape mode:

Next I added these lines of code to the view controllers I wanted to be Portrait:

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationPortrait;
}
-(BOOL)shouldAutorotate
{
    return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

However when I rotate them they still go to landscape mode.How can I fix that?

回答1:

Here is how I do it.
Make a UINavigationController parent class.
inside you UINavigationController (parent) override these methods like:

- (NSUInteger)supportedInterfaceOrientations
{
    if([self.topViewController respondsToSelector:@selector(supportedInterfaceOrientationsForThisContorller)])
    {
        return(NSInteger)[self.topViewController performSelector:@selector(supportedInterfaceOrientationsForThisContorller) withObject:nil];
    }
    return UIInterfaceOrientationPortrait;
}

- (BOOL)shouldAutorotate
{
    if([self.visibleViewController respondsToSelector:@selector(shouldAutorotateNow)])
    {
        BOOL autoRotate = (BOOL)[self.visibleViewController
                            performSelector:@selector(shouldAutorotateNow)
                            withObject:nil];
        return autoRotate;

    }
    return NO;
}

Now your NavigationController should be a subclass of the UINavigationContorller parent

Swift 3:

Inside your UINavigationController subclass do this

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        get {
            return self.topViewController?.supportedInterfaceOrientations ?? .all
        }
    }

override var shouldAutorotate: Bool {
        return self.topViewController?.shouldAutorotate ?? false
    }

Update Taken from Matt's answer if you don't want to subclass:

first: make your viewController a delegate of the navigationController in viewDidLoad

self.navigationController?.delegate = self

Then declare UIViewController extension to respond to the delegate method as shown below:

extension UIViewController: UINavigationControllerDelegate {
    public func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
        return navigationController.topViewController?.supportedInterfaceOrientations
    }
}


回答2:

The Apple designed way to do this for UINavigationController is via UINavigationControllerDelegate.

Usually I just update this delegate to do the following and delegate it to the top displaying controller in the navigation controller's stack:

#pragma mark - UINavigationControllerDelegate

- (NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController
{
    return [navigationController.topViewController supportedInterfaceOrientations];
}

In my opinion the UINavigationController should just default to the above behavior but this is the api Apple has provided :)

As for the info plist file I uncheck all of the options and handle it all in code as it has caused issues for me in the past and I got tired of dealing with it.



回答3:

Just for you all information, create a new project single view based Application, implement the should auto rotate delegate and the supportedInterface orientation in viewController add breakpoint in it.

The run (universal mode)

  1. on iphone simulator : execution stops at breakpoints
  2. on ipad Simulator : executions DOESN'T STOP (delegate methods are never called !!!!)
  3. on ipad device : ok

So don't waste too mush time on it like I juste Did, XCode 7.3 is BUGGED



回答4:

You can see the answer in the following post:

iOS 6 rotations: supportedInterfaceOrientations doesn´t work?

Let me know if it's your problem.



回答5:

When under UINavigationController, I'm implementing the UINavigationControllerDelegate and the following method:

#pragma mark - From UINavigationControllerDelegate

-(UIInterfaceOrientationMask) navigationControllerSupportedInterfaceOrientations:(UINavigationController*)navigationController {
    return UIInterfaceOrientationMaskPortrait; // TODO: change to whatever you need to allow
}