Portrait by default, How can some special screens auto rotated or force some screens to landscape?

Viewed 57

In my app, the orientation is portrait by default, but in some special screens I want the viewcontroller to be auto rotated or to force the orientation to landscape.

in AppDelegate.swift :

class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?

// portrait by default
var interfaceOrientations:UIInterfaceOrientationMask = .portrait {
    didSet{
        // force to portrait
        if interfaceOrientations == .portrait {
            UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue,
                                      forKey: "orientation")
        }
            // force to landscape
        else if !interfaceOrientations.contains(.portrait){
            UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue,
                                      forKey: "orientation")
        }
    }
}

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

in only portrait vc:

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

    appDelegate.interfaceOrientations = .portrait
}

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

    appDelegate.interfaceOrientations = .portrait
}

in auto rotated vc:

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

    appDelegate.interfaceOrientations = .allButUpsideDown
}

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

    appDelegate.interfaceOrientations = .portrait
}

in only landscape vc:

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

    appDelegate.interfaceOrientations = [.landscapeLeft, .landscapeRight]
}

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

    appDelegate.interfaceOrientations = .portrait
}

but it still has bugs...Help me

2 Answers

You should force the rotation with:

UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")

You also have to enable autoRotation

override var shouldAutorotate: Bool{
    return true
}

And of course, in your project settings you have to enable both portrait and landscapes modes.

You can custom your Portrait View Controller and Landscape View Controller. LandscapeViewController like this:

```

 override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
 }

 override var shouldAutorotate: Bool {
    return true
 }

 override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .landscapeRight
 }

 override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .landscapeRight
 }

```

Some points need to notice: UIViewController can't decide to rotate automatically, you can use UINavigationController to fetch the value of rotation property:

override var shouldAutorotate: Bool {
    return (self.topViewController?.shouldAutorotate)!
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return (self.topViewController?.supportedInterfaceOrientations)!
}

override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return (self.topViewController?.preferredInterfaceOrientationForPresentation)!
}
Related