简体   繁体   中英

Locked ViewController orientation breaking when segueing back and forth

I have a simple camera app. The Camera Preview screen is a viewcontroller (name ViewController) which I locked the orientation via this code (can't find the StackOverflow link to this code), The viewcontroller is embedded in a navigation controller:

 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        if let navigationController = self.window?.rootViewController as? UINavigationController {
            if navigationController.visibleViewController is ViewController {
                return UIInterfaceOrientationMask.portrait
            } else {
                return UIInterfaceOrientationMask.all
            }
        }
        return UIInterfaceOrientationMask.portrait
    }

When the camera starts up, the Camera Preview is locked in .portrait orientation, which is what I desire. However, if I hit the library button, which segues me to another screen, and change the orientation of the library screen by rotating my physical device, and THEN return back to my Camera Preview screen via the "back" button, the orientation is broken. It's in landscape mode, instead of portrait mode. How do I get a hard lock?

Just incase, I made a dummy model of my code here (too long to post here), where you guys can test it out yourself

https://github.com/bigmit2011/Testing-Camera

EDIT:

If the app crashes just try running it one more time. For some reason the first time the app is ran it crashes. Thank you.

EDIT2:

Attempting to set embedded ViewController as a delegate of UINavigationController. However, I don't quite understand if I'm doing it correctly:

class ViewController: UIViewController, UINavigationControllerDelegate {

    var navigation: UINavigationController?
    self.navigation.delegate = self  // doesn't seem to work


    func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {

        return .portrait
    }

Do I need to create a separate swift file for the UiNavigationController?

EDIT3: Following Matt's answer code is as follows:

class CameraViewController :UIViewController, UINavigationControllerDelegate {

override func viewDidLoad() {

    self.navigationController?.delegate = self
    super.viewDidLoad()

func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {

        return .portrait
    }

However, this seems to lock everything in portrait mode not just that single viewController embedded within Navigation Controller.

You are making two mistakes.

  • First, you are trying to govern the orientation of individual view controllers from the app delegate. That's wrong. The app delegate governs the totality of possible orientations for the whole app. But as for view controllers, each individual view controller governs its own orientation. Just implement supportedInterfaceOrientations in each of your two view controllers (not in the app delegate).

  • Second, your first view controller is in a navigation interface. Therefore it is not the top-level view controller and cannot govern orientation directly (with supportedInterfaceOrientations ). The correct way to govern the orientation of a navigation interface is to set yourself as the navigation controller's delegate and implement navigationControllerSupportedInterfaceOrientations(_:) .

I also couldn't run your app. But I tested this in Xcode with a main VC, a 2nd VC and embedded the main VC in a navigation controller. I then followed the advice in this article Selective rotation lock in iOS

You add the following to AppDelegate:

var enableAllOrientation = false

func application(_ application: UIApplication,supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if (enableAllOrientation == true){
    return UIInterfaceOrientationMask.allButUpsideDown
}
return UIInterfaceOrientationMask.portrait
}

Then in the VC that allows allButUpsideDown (or change this to what you want), you add the following code:

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.enableAllOrientation = true
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.enableAllOrientation = false

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

I put this in the 2nd VC. Ran the app in the simulator, segued to the 2nd VC, changed the orientation to landscape then hit back and the main VC was locked in portrait.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM