2

I have an app with several VCs embedded in a NavigationController.

I need all VCs to be locked in a portrait orientation and only one in both portrait and landscape.

I've tried different approaches and this one is working for me:

extension UINavigationController {
public override func supportedInterfaceOrientations() -> Int {
return visibleViewController.supportedInterfaceOrientations()
}
public override func shouldAutorotate() -> Bool {
return visibleViewController.shouldAutorotate()
}

}

And then I modify each ViewController like this:

class ViewController: UIViewController {
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

}

All is well when I open the app and go from one VC to another. The views that should be only Portrait are only Portrait. Then I open the view that wasn't modified and it changes the interfaceOrientation as intended.

BUT then let's say I leave the last unmodified view in Landscape and I press a back button in NavBar and go to the previous controller (which was modified to be only Portrait). The layout of the VC is shown as Landscape.

And if I keep pressing back button, all other VC behave like they were never told to be only portrait.

I used this post Korey Hinton, Lock Screen Rotation

Peter O.
  • 32,158
  • 14
  • 82
  • 96
alahab
  • 85
  • 1
  • 9

2 Answers2

1

I think I was able to replicate the scenario you described. Unfortunately the normal ways I try to force it to update didn't work but I did find this SO answer that seems to work. Put this in the view controller you return back to in viewDidAppear:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

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

This fix seemed to work for me. It is a pretty rough transition though. I hope that helps

Community
  • 1
  • 1
Korey Hinton
  • 2,532
  • 2
  • 25
  • 24
0

I had this problem with presented view controllers and orientation lock differences. I added this into the "unlocked" controller:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self willRotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft duration:0];
}

So when that controller is about to be removed (back button pressed) it sends a message that it should return to landscape (it doesn't matter left or right because the pervious controller will autorotate from that to the proper orientation). That's in objective-c, but I'm sure there is an analogous operation in swift. You may have to mess with the animation duration if it makes things look weird, but mine worked perfectly with an immediate switch.

Putz1103
  • 6,211
  • 1
  • 18
  • 25
  • Thanks! I was trying to translate in into swift. When i try to implement `willRotateToInterfaceOrientation` it says "willRotateToInterfaceOrientation(_:duration:)' was deprecated in iOS version 8.0: Implement viewWillTransitionToSize:withTransitionCoordinator: instead. In this answer [http://stackoverflow.com/questions/26943808/ios-how-to-run-a-function-after-device-has-rotated-swift] there must be some code pasted inside viewWillTransitionToSize. Do you have any idea how it should properly look in iOS8 and Swift? – alahab May 27 '15 at 15:28
  • I do not. I have not had the opportunity to work in depth in swift yet. I have a bunch of legacy code that I support. I would try manualling calling that transitiontosize function instead of willrotate. I'm guessing you can find a set op parameters to send that will do what you need. – Putz1103 May 27 '15 at 15:34