Configure ViewController rotation settings in Swift 3 on iOS 10

I have an app which was developed to run in Portrait orientation only.


Prior to iOS 10 and Swift 3, I could use the following code in the ViewController -

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {

return UIInterfaceOrientationMask.portrait

}

override func shouldAutorotate() -> Bool {

return true

}


However after migrating my project to Swift 3 in Xcode 8 (Beta 6), the above code shows the error - “Method does not override any method from its superclass”, and does not compile.


So I checked the API Reference, and it appears that shouldAutorotate and supportedInterfaceOrientations are now defined as get-only properties for ViewControllers in Swift as follows -

var shouldAutorotate: Bool { get }

var supportedInterfaceOrientations: UIInterfaceOrientationMask { get }


So how can we set these values if they are get-only properties? I tried the following in the the AppDelegate’s didFinishLaunchingWithOptions function -

if let vController = self.window?.rootViewController as? ViewController{

vController.shouldAutorotate = true

}

But it gives an error message saying - Cannot assign to property: ‘shouldAutorotate’ is a get-only property


Can anyone shed some light on how to configure the shouldAutorotate and supportedInterfaceOrientations parameters for individual ViewControllers?

Accepted Reply

Since they have changed from funcs to vars, you also need to override them as vars. Get-only (read-only) vars can be written without the get{} specifier if you want to save a few keystrokes:

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }
  
    override var shouldAutorotate: Bool {
        return false
    }

Replies

Since they have changed from funcs to vars, you also need to override them as vars. Get-only (read-only) vars can be written without the get{} specifier if you want to save a few keystrokes:

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }
  
    override var shouldAutorotate: Bool {
        return false
    }

I have has the same problem and the suggested solution does only seem to work on swift 3.

If you use swift 2.3 the supportedInterfaceOrientations signature is still the old one and not a var.


The problem is that the old signature never gets called, so any ideas what you can do in Swift 2.3?

Simple not working on xcode 8 swift 3 .


  override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }
   
    override var shouldAutorotate: Bool {
        return false
    }


i have no error on this code bu still not working ...

i also setup in project setting general porttrain ....

Even i face the similar issue . I am building my app in iOS 9 SDK (Xcode 7.x) which will run in iOS 10 as well. (Objective - C)

I cannot set the project to general portrait coz it supports both the orientations. In only one VC i am using Portrait mode.

supportedInterfaceOrientations not called

That's strange, I just created a new app with one view controller and did't change any settings, and these properties got queried. I added another view controller, added a button on the first with a segue to the second, and these properties did not get queried in either VC. I turned on the "Requires full screen" setting (under "Deployment Info" in the target settings), and these properties were queried again. Then, I deleted the second view controller so I only had one again, and I still needed the "Requires full screen" setting to be on to have these properties queried.

So I tried it again with a new app with one view controller and didn't change any settings, and this time these properties were not queried. Then I turned on "Requires full screen", and they were queried.

So I guess you must have to have "Requires full screen" on to make sure these properties get queried.

I also went to the deployment info, and unchecked the landscape views. After that I didn't need the override var shouldAutorotate, nor the other one. Both my screens are now fixed in portrait. Raises the question what if you want one screen to be fixed portrait and the next to have both protrait and landscape..

It will raise an exception, since you permited only a portrait view and you are forcing a view wich is not predicted in the project settings. guywithmazda code works, what you have to do is:

Make sure you are putting this code snippet in the right view controller. For example, if the View Controller is embedded in a UINavigationController, the navigation controller can still rotate, causing the View Controller to still rotate. So, you have to put this code in the UINavigationController class instead. It really depends on your specific situation.


Why are you posting programming questions here, instead of stackoverflow?

You can have a question sit here for years unanswered, or go to stackoverflow and get it answered in a few hours.

Just makes no sense to ever post a programming question here.

I doubt this is how apple intended it be used... to ask programming questions.

If they did, they'd have done it properly and made a site like stackoverflow with tags, categories, voting up best answers, comprehensive searching and filtering, etc.

This code below don't work for all case... If you want to use it in all cases and singol viewController, you should do the following:


Add to your AppDelegate file:


var orientationLock = UIInterfaceOrientationMask.all

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

return self.orientationLock

}


struct AppUtility {

static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {

if let delegate = UIApplication.shared.delegate as? AppDelegate {

delegate.orientationLock = orientation

}

}


static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {

self.lockOrientation(orientation)

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

}

}


Add to the viewcontroller that you want to force an orientation:


override func viewDidAppear(_ animated: Bool) {

super.viewDidAppear(animated)

AppDelegate.AppUtility.lockOrientation(.portrait)

}


override func viewWillDisappear(_ animated: Bool) {

super.viewWillDisappear(animated)

AppDelegate.AppUtility.lockOrientation(.all)

}

Hello!!


Would this work for iMessage extensions, too? Looks like, it isn't. :-/


Thanks in advance.


Regards,

Shyam