Setting device orientation in Swift iOS

SwiftIos8Rotation

Swift Problem Overview


I am working on a swift app for iPhone. There is a modal view in my application that I want only to be in portrait view.

My question is, how do I programmatically force the phone to not allow rotation? In other words, I am looking for code that will not allow a modal view to be displayed in landscape mode (turning on portrait rotation lock).

This is just for 1 modal view, so I can't turn off rotation for the entire app, otherwise I would just disable rotation altogether.

I found code in my research here But it is in objective C, in case that helps. Thanks!

Swift Solutions


Solution 1 - Swift

Hi for LandscapeLeft and LandscapeRight (Update Swift 2.0)

enter image description here And you have this in info

enter image description here

And UIController

override func shouldAutorotate() -> Bool {
    return true
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return [UIInterfaceOrientationMask.LandscapeLeft,UIInterfaceOrientationMask.LandscapeRight]
}

For PortraitUpsideDown and Portrait use that enter image description here

override func shouldAutorotate() -> Bool {
    if (UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft ||
        UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight ||
        UIDevice.currentDevice().orientation == UIDeviceOrientation.Unknown) {
            return false
    }
    else {
        return true
    }
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return [UIInterfaceOrientationMask.Portrait ,UIInterfaceOrientationMask.PortraitUpsideDown]
}

Message from France, Merry Christmas !

Edit :

Other solution :

extension UINavigationController {
    public override func shouldAutorotate() -> Bool {
        if visibleViewController is MyViewController {
            return true   // rotation
        } else {
            return false  // no rotation
        }
    }
    
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return (visibleViewController?.supportedInterfaceOrientations())!
    }
}

Solution 2 - Swift

You can paste these methods in the ViewController of each view that needs to be portrait:

override func shouldAutorotate() -> Bool {
    return false
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}

Solution 3 - Swift

Swift 3

Orientation rotation is more complicated if a view controller is embedded in UINavigationController or UITabBarController the navigation or tab bar controller takes precedence and makes the decisions on autorotation and supported orientations.

Use the following extensions on UINavigationController and UITabBarController so that view controllers that are embedded in one of these controllers get to make the decisions:

UINavigationController extension

extension UINavigationController {

override open var shouldAutorotate: Bool {
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation{
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.preferredInterfaceOrientationForPresentation
        }
        return super.preferredInterfaceOrientationForPresentation
    }
}

override open var supportedInterfaceOrientations: UIInterfaceOrientationMask{
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }
 }}

UITabBarController extension

extension UITabBarController {

override open var shouldAutorotate: Bool {
    get {
        if let selectedVC = selectedViewController{
            return selectedVC.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation{
    get {
        if let selectedVC = selectedViewController{
            return selectedVC.preferredInterfaceOrientationForPresentation
        }
        return super.preferredInterfaceOrientationForPresentation
    }
}

override open var supportedInterfaceOrientations: UIInterfaceOrientationMask{
    get {
        if let selectedVC = selectedViewController{
            return selectedVC.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }
}}

Now you can override the supportedInterfaceOrientations, shouldAutoRotate and preferredInterfaceOrientationForPresentation in the view controller you want to lock down otherwise you can leave out the overrides in other view controllers that you want to inherit the default orientation behavior specified in your app's plist.

Lock to Specific Orientation

class YourViewController: UIViewController {
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask{
    get {
        return .portrait
    }
}}

Disable Rotation

    class YourViewController: UIViewController {
open override var shouldAutorotate: Bool {
    get {
        return false
    }
}}

Change Preferred Interface Orientation For Presentation

class YourViewController: UIViewController {
open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation{
    get {
        return .portrait
    }
}}

Solution 4 - Swift

Above code might not be working due to possibility if your view controller belongs to a navigation controller. If yes then it has to obey the rules of the navigation controller even if it has different orientation rules itself. A better approach would be to let the view controller decide for itself and the navigation controller will use the decision of the top most view controller.

> We can support both locking to current orientation and autorotating to lock on a specific orientation with this generic extension on UINavigationController: -:

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

Now inside your view controller we can

class ViewController: UIViewController {
    // MARK: Autoroate configuration
    
    override func shouldAutorotate() -> Bool {
        if (UIDevice.currentDevice().orientation == UIDeviceOrientation.Portrait ||
            UIDevice.currentDevice().orientation == UIDeviceOrientation.PortraitUpsideDown ||
            UIDevice.currentDevice().orientation == UIDeviceOrientation.Unknown) {
                return true
        }
        else {
            return false
        }
    }
    
    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.Portrait.rawValue) | Int(UIInterfaceOrientationMask.PortraitUpsideDown.rawValue)
    }
}

Hope it helps. Thanks

Solution 5 - Swift

This will disable autorotation of the view:

override func shouldAutorotate() -> Bool {
    return false;
}

Update

override func shouldAutorotate() -> Bool {
    if (UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft ||
        UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight ||
        UIDevice.currentDevice().orientation == UIDeviceOrientation.Unknown) {
            return false;
    }
    else {
        return true;
    }
}

If app is in landscape mode and you show a view which must be showed in portrait mode, this will allow app to change it's orientation to portrait (of course when device will be rotated to such orientation).

Solution 6 - Swift

If someone wants the answer, I think I just got it. Try this:

  • Go to your .plist file and check all the orientations.
  • In the view controller you want to force orientation, add the following code:

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait.toRaw().hashValue | UIInterfaceOrientationMask.PortraitUpsideDown.toRaw().hashValue
}

Hope it helps !

EDIT :

To force rotation, use the following code :

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

It works for iOS 7 & 8 !

Solution 7 - Swift

enter image description here

Go to your pList and add or remove the following as per your requirement:

"Supported Interface Orientations" - Array
"Portrait (bottom home button)" - String
"Portrait (top home button)" - String
"Supported Interface Orientations (iPad)" - Array
"Portrait (bottom home button)" - String
"Portrait (top home button)" - String
"Landscape (left home button)" - String
"Landscape (right home button)" - String

Note: This method allows rotation for a entire app.

OR

Make a ParentViewController for UIViewControllers in a project (Inheritance Method).

//  UIappViewController.swift

import UIKit

class UIappViewController: UIViewController {
          super.viewDidLoad()   
    }
//Making methods to lock Device orientation.
    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
    override func shouldAutorotate() -> Bool {
        return false
    }                                                                                                                                       
    override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }

Associate every view controller's parent controller as UIappViewController.

//  LoginViewController.swift

import UIKit
import Foundation

class LoginViewController: UIappViewController{

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

Solution 8 - Swift

For Swift 3, iOS 10

override open var shouldAutorotate: Bool {
    return false
}

override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .portrait
}

override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .portrait
}

However, there is a bug with the setting shouldAutorotate doesn't work on iOS 9 currently.

Solution 9 - Swift

In info.plist file , change the orientations which you want in "supported interface orientation".

In swift the way supporting files->info.plist->supporting interface orientation.

Solution 10 - Swift

I've been struggling all morning to get ONLY landscape left/right supported properly. I discovered something really annoying; although the "General" tab allows you to deselect "Portrait" for device orientation, you have to edit the plist itself to disable Portrait and PortraitUpsideDown INTERFACE orientations - it's the last key in the plist: "Supported Interface Orientations".

The other thing is that it seems you must use the "mask" versions of the enums (e.g., UIInterfaceOrientationMask.LandscapeLeft), not just the orientation one. The code that got it working for me (in my main viewController):

override func shouldAutorotate() -> Bool {
    return true
}

override func supportedInterfaceOrientations() -> Int {
    return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue) | Int(UIInterfaceOrientationMask.LandscapeRight.rawValue)
}

Making this combination of plist changes and code is the only way I've been able to get it working properly.

Solution 11 - Swift

More Swift-like version:

override func shouldAutorotate() -> Bool {
    switch UIDevice.currentDevice().orientation {
    case .Portrait, .PortraitUpsideDown, .Unknown:
        return true
    default:
        return false
    }
}

override func supportedInterfaceOrientations() -> Int {
    return Int(UIInterfaceOrientationMask.Portrait.rawValue) | Int(UIInterfaceOrientationMask.PortraitUpsideDown.rawValue)
}

UINavigationController from Vivek Parihar

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

Solution 12 - Swift

// Swift 2

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    let orientation: UIInterfaceOrientationMask =
    [UIInterfaceOrientationMask.Portrait, UIInterfaceOrientationMask.PortraitUpsideDown]
    return orientation
}

Solution 13 - Swift

Two suggestions with @Vivek Parihar's solution :

  1. If we are presenting any viewController we should check nil for “visibleViewController” in navigationController extension

     extension UINavigationController {
     public override func shouldAutorotate() -> Bool {
         var shouldAutorotate = false
         if visibleViewController != nil {
             shouldAutorotate = visibleViewController.shouldAutorotate()
         }
         return shouldAutorotate
     }
     
     public override func supportedInterfaceOrientations() -> Int {
         return visibleViewController.supportedInterfaceOrientations()
     }
     }
    
  2. If We are using any action sheet to present and user will rotate upsideDown, Your action sheet will open from top edge of the screen :P, to solve this, we should take Portrait only

    override func shouldAutorotate() -> Bool {
    if (UIDevice.currentDevice().orientation == UIDeviceOrientation.Portrait ||
        UIDevice.currentDevice().orientation == UIDeviceOrientation.Unknown) {
            return true
    }
    else {
        return false
    }
    

    }

    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.Portrait.rawValue)
    }
    

Solution 14 - Swift

Swift 2.2

    func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
  
    if self.window?.rootViewController?.presentedViewController is SignatureLandscapeViewController {
        
        let secondController = self.window!.rootViewController!.presentedViewController as! SignatureLandscapeViewController
        
        if secondController.isPresented {
            
            return UIInterfaceOrientationMask.LandscapeLeft;
            
        } else {
            
            return UIInterfaceOrientationMask.Portrait;
        }
        
    } else {
        
        return UIInterfaceOrientationMask.Portrait;
    }
}

Solution 15 - Swift

My humble contribution (Xcode 8, Swift 3):

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController) {
            if (rootViewController.responds(to: Selector(("canRotate")))) {
                // Unlock landscape view orientations for this view controller
                return .allButUpsideDown;
            }
        }
        return .portrait;        
    }
    
    private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController? {
        if (rootViewController == nil) { return nil }
        if (rootViewController.isKind(of: (UITabBarController).self)) {
            return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController)
        } else if (rootViewController.isKind(of:(UINavigationController).self)) {
            return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController)
        } else if (rootViewController.presentedViewController != nil) {
            return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController)
        }
        return rootViewController
    }

... on the AppDelegate. All the credits for Gandhi Mena: http://www.jairobjunior.com/blog/2016/03/05/how-to-rotate-only-one-view-controller-to-landscape-in-ios-slash-swift/

Solution 16 - Swift

From ios 10.0 we need set { self.orientations = newValue } for setting up the orientation, Make sure landscape property is enabled in your project.

private var orientations = UIInterfaceOrientationMask.landscapeLeft
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
    get { return self.orientations }
    set { self.orientations = newValue }
}

Solution 17 - Swift

Swift 4:

The simplest answer, in my case needing to ensure one onboarding tutorial view was portrait-only:

extension myViewController {
    //manage rotation for this viewcontroller
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
}

Eezy-peezy.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionrocket101View Question on Stackoverflow
Solution 1 - SwiftYannStephView Answer on Stackoverflow
Solution 2 - SwiftDrOverbuildView Answer on Stackoverflow
Solution 3 - SwiftDragosView Answer on Stackoverflow
Solution 4 - SwiftVivek PariharView Answer on Stackoverflow
Solution 5 - SwiftnsinvocationView Answer on Stackoverflow
Solution 6 - SwiftlobodartView Answer on Stackoverflow
Solution 7 - SwiftAlvin GeorgeView Answer on Stackoverflow
Solution 8 - SwiftCodeOverRideView Answer on Stackoverflow
Solution 9 - SwiftMaluView Answer on Stackoverflow
Solution 10 - SwiftjbmView Answer on Stackoverflow
Solution 11 - SwiftVojtech VrbkaView Answer on Stackoverflow
Solution 12 - Swiftuser3561494View Answer on Stackoverflow
Solution 13 - SwiftNiteshView Answer on Stackoverflow
Solution 14 - Swiftidris yıldızView Answer on Stackoverflow
Solution 15 - SwiftIvan MoralesView Answer on Stackoverflow
Solution 16 - SwiftJackView Answer on Stackoverflow
Solution 17 - Swiftdrew..View Answer on Stackoverflow