Locking device orientation on a view fails when going back in NavBar
Asked Answered
S

2

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

Slim answered 27/5, 2015 at 14:56 Comment(0)
L
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

Lathery answered 28/5, 2015 at 19:48 Comment(1)
You are right, the transition is pretty rough, but at least it did the job for me. Thanks a lot for taking your time to answer, Korey. I really appreciate it!Slim
H
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.

Hazelton answered 27/5, 2015 at 15:8 Comment(2)
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 [#26944308 there must be some code pasted inside viewWillTransitionToSize. Do you have any idea how it should properly look in iOS8 and Swift?Slim
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.Hazelton

© 2022 - 2024 — McMap. All rights reserved.