Disable rotation for View Controller in Navigation

2019-01-26 17:49发布

First of all, this isn't a duplicate. I've looked at all of the questions related to this on SO and none of them work for me. Hopefully it's just because I'm new to iOS development but I suspect this isn't possible in my case. I've attached a picture with the view controller circled that I want to disable rotation for.

I've already tried: Subclassing the view controller that I want to disable rotation for and using the shouldAutoRotate method by setting it to NO. Apparently this doesn't work because it's the navigation controller that dictates whether its view controllers can rotate. So, I subclassed UINavigationController and used this class in storyboard instead of the default navigation controller. In this class I've set shouldAutoRotate to NO. It still doesn't work. Don't really know what I'm doing wrong.

When I extend the root view controller with my view controller class with shouldAutoRotate set to NO, it disables rotation...for the whole app. This is not what I want. I only want the rotation to be disabled for the view controller circled in the picture.

enter image description here

Thanks in advance!

6条回答
戒情不戒烟
2楼-- · 2019-01-26 18:15

UINavigationController+Rotation Category

When u usign navigation controller SupportedInterfaceOrientaions of ViewController will not work adding this category to ur Project will get the response from your viewController also instead of NavigationController alone.

查看更多
聊天终结者
3楼-- · 2019-01-26 18:19

My case has 3 view controller:
- first view controller: portrait
- second view controller: landscape right (has navigation controller and was presented by first view controller)
- third view controller: portrait (has navigation controller and was pushed by second view controller )
And this is my solution in swift 3:
------------------------------------
At AppDelegate:
- Add this property to save your setting

private var orientation: UIInterfaceOrientationMask = .portrait

-Then create a function to set rotate for your device:

func rotateScreen(orientation: UIInterfaceOrientationMask) {
    self.orientation = orientation
    var value = 0;
    if orientation == .landscapeRight {
        value = UIInterfaceOrientation.landscapeRight.rawValue
    }else {
        value = UIInterfaceOrientation.portrait.rawValue
    }
    UIDevice.current.setValue(value, forKey: "orientation")
}

- Finally, implement support orientation method:

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return self.orientation
}

--------------------------------
Then you can call like this before display destination view controller

(UIApplication.shared.delegate as! AppDelegate).rotateScreen(orientation: .landscapeRight)

For example, in my case: When user tap on button at the First to present the Second, I'll do like this

(UIApplication.shared.delegate as! AppDelegate).rotateScreen(orientation: .landscapeRight)
self.present(navigation, animated: true, completion: nil)

And the close button at the Second I'll do like this

(UIApplication.shared.delegate as! AppDelegate).rotateScreen(orientation: .portrait)
self.dismiss(animated: true, completion: nil)

That's all! You could never mind using navigation controller or not. Hope this helps you guys ^__^!

查看更多
在下西门庆
4楼-- · 2019-01-26 18:21

Add your AppDelegate.h

@property (nonatomic , assign) bool blockRotation;

AppDelegate.m

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

In view Controller that you want to disable rotation

- (void)viewDidLoad
{
 [super viewDidLoad];
    AppDelegate* shared=[UIApplication sharedApplication].delegate;
    shared.blockRotation=YES;
}

-(void)viewWillDisappear:(BOOL)animated{
  AppDelegate* shared=[UIApplication sharedApplication].delegate;
  shared.blockRotation=NO;

  }
查看更多
姐就是有狂的资本
5楼-- · 2019-01-26 18:27

Thanks to @ozgur for the fix which worked for me. I would 'vote up', but apparently I'm not good enough (whatever!) to vote whether a fix works or not. Anyway, here it is in Swift:

In AppDelegate.swift:

class AppDelegate: UIResponder, UIApplicationDelegate {


var blockRotation: Bool = false

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {

    if (self.blockRotation) {
        println("supportedInterfaceOrientations - PORTRAIT")
        return Int(UIInterfaceOrientationMask.Portrait.rawValue)
    } else {
        println("supportedInterfaceOrientations - ALL")
        return Int(UIInterfaceOrientationMask.All.rawValue)
    }
}

In the ViewController that you want to block rotation, add UIApplicationDelegate to your class...

class LoginViewController: UIViewController, UITextFieldDelegate, UIApplicationDelegate {

and then create a reference to the AppDelegate...

var appDelegate = UIApplication.sharedApplication().delegate as AppDelegate

In viewDidLoad, set appDelegate.blockRotation = true:

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.

    appDelegate.blockRotation = true

}

In viewWillAppear, set the orientation to force the device to the chosen orientation (Portrait in this example):

override func viewWillAppear(animated: Bool) {

    let value = UIInterfaceOrientation.Portrait.rawValue
    UIDevice.currentDevice().setValue(value, forKey: "orientation")

}

Then in viewWillDisappear, or in prepareForSegue, set appDelegate.blockRotation = false:

override func viewWillDisappear(animated: Bool) {
    appDelegate.blockRotation = false
}

This worked for me in this exact (multiple view controllers in a Navigation Controller) scenario, after many hours of reading other solutions on this site. Thanks again to @ozgur - I'd up-vote your answer if I could!

Happy trails!

查看更多
Juvenile、少年°
6楼-- · 2019-01-26 18:33

For those of you using Swift 2, you can follow Andre's answer, but in step one, use the code below in your AppDelegate.swift:

class AppDelegate: UIResponder, UIApplicationDelegate {


var blockRotation: Bool = false

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {

    if (self.blockRotation) {
        print("supportedInterfaceOrientations - PORTRAIT")
        return UIInterfaceOrientationMask.Portrait
    } else {
        print("supportedInterfaceOrientations - ALL")
        return UIInterfaceOrientationMask.All
    }
}

supportedInterfaceOrientationsForWindow: now returns a UIInterfaceOrientationMask instead of an Int.

查看更多
Ridiculous、
7楼-- · 2019-01-26 18:35

You have to check in your root view controller is rotation allowed in current top controller and return YES or NO in supportedInterfaceOrientations method. So it should be like the following code in your root controller (adapt the code to your case):

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

Then in each view controller add supported interface orientations, for example:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}
查看更多
登录 后发表回答