iosswiftorientationuidevice

UIDevice orientation returns portrait when device launches as landscape


Heres a sample code that will print if the device is "portrait" or "landscape" when it first launches and also when it detects an orientation change.

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        getOrientation()
    }

    func getOrientation() {
        let orientation = UIDevice.current.orientation
        if orientation == .landscapeLeft || orientation == .landscapeRight {
            print("landscape")
        }
        else {
            print("portrait")
        }
    }
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        getOrientation()
    }
}

If I launch the app with the phone portrait, it works fine. However, if I launch the app with the phone in landscape, it'll detect portrait at first. But if you rotate the device afterward it'll be correct. Is this a bug or am I using UIDevice.current.orientation incorrectly?


Solution

  • See, your code is perfect, but the calling is not proper. viewDidLoad method doesn't guarantees the interface orientation or any UI related properties things it just says that view is loaded but in case if you want to guarantee to get the proper details then you should call it under DispatchQueue.main.async(execute: block) (Main queue) which will give proper orientation or the other way is to call under viewDidLayoutSubviews but this has an disadvantage of calling multiple times depending on your views and subviews are resized.

    DispatchQueue.main.async {
        self.getOrientation()
    }
    

    Reference: view.frame.width IS correct in viewDidLoad with storyboard, why?

    Apple Docs: https://developer.apple.com/documentation/uikit/uiviewcontroller