skip to Main Content

According to the iOS & iPadOS 16 Beta 3 Release Notes:- Attempting to set an orientation on UIDevice via setValue:forKey: isn’t supported and no longer works. Instead, they say use: preferredInterfaceOrientationForPresentation.

In my case, force view controller orientation is not working in iOS 16 beta either by using preferredInterfaceOrientationForPresentation or requestGeometryUpdate.

Previously, UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation") was working fine.

8

Answers


  1. I noticed my issue seems like resolved by calling method below:

    [UIViewController setNeedsUpdateOfSupportedInterface

    You may give it a try.

    Login or Signup to reply.
  2. setValue:forKey is a method of old NSObject (NSKeyValueCoding). It’s not official documented and supported by UIDevice class. Using it is considering using a private api. Apple can terminate it anytime they want.

    Login or Signup to reply.
  3. My problem with my code below is that I’m trying to do it when closing a modal view and the view under it are not updated quick enough. If I put the requestGeometryUpdate on a separate button then when I close the view it work.

    if #available(iOS 16.0, *) {
    
        let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
    
        windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait))
    
    } 
    
    Login or Signup to reply.
  4. Apple released new API which is replaced with setValue:forKey:"orientation".
    Apple update

    guard let windowScene = view.window?.windowScene else { return }
    windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .landscape)) { error in
    // Handle denial of request.
    }
    

    But I am having problem about UIDevice.orientationDidChangeNotification , it is not working

    Login or Signup to reply.
  5. It works for me.

    In AppDelegate,

    var orientation: UIInterfaceOrientationMask = .portrait
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return orientation
    }
    

    In view controller,

    (UIApplication.shared.delegate as? AppDelegate)?.orientation = .landscapeRight
                        
    let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
    windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: .landscapeRight))
    
    UIApplication.navigationTopViewController()?.setNeedsUpdateOfSupportedInterfaceOrientations()
    

    In Helper,

    extension UIApplication {
        class func navigationTopViewController() -> UIViewController? {
            let nav = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController
            return  nav?.topViewController
        }
    }
    
    Login or Signup to reply.
  6. It works for me:

    import Foundation
    import UIKit
    
    extension UIViewController {
        
        func setDeviceOrientation(orientation: UIInterfaceOrientationMask) {
            if #available(iOS 16.0, *) {
                let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
                windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))
            } else {
                UIDevice.current.setValue(orientation.toUIInterfaceOrientation.rawValue, forKey: "orientation")
            }
        }
    }
    
    extension UIInterfaceOrientationMask {
        var toUIInterfaceOrientation: UIInterfaceOrientation {
            switch self {
            case .portrait:
                return UIInterfaceOrientation.portrait
            case .portraitUpsideDown:
                return UIInterfaceOrientation.portraitUpsideDown
            case .landscapeRight:
                return UIInterfaceOrientation.landscapeRight
            case .landscapeLeft:
                return UIInterfaceOrientation.landscapeLeft
            default:
                return UIInterfaceOrientation.unknown
            }
        }
    }
    

    How to use it?

    Just call it on your UIViewController:

    setDeviceOrientation(orientation: .landscapeRight)
    

    EDIT

    More completed solution:

    import UIKit
    
    final class DeviceOrientation {
        
        static let shared: DeviceOrientation = DeviceOrientation()
        
        // MARK: - Private methods
        
        private var windowScene: UIWindowScene? {
            return UIApplication.shared.connectedScenes.first as? UIWindowScene
        }
        
        // MARK: - Public methods
        
        func set(orientation: UIInterfaceOrientationMask) {
            if #available(iOS 16.0, *) {
                windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))
            } else {
                UIDevice.current.setValue(orientation.toUIInterfaceOrientation.rawValue, forKey: "orientation")
            }
        }
        
        var isLandscape: Bool {
            if #available(iOS 16.0, *) {
                return windowScene?.interfaceOrientation.isLandscape ?? false
            }
            return UIDevice.current.orientation.isLandscape
        }
        
        var isPortrait: Bool {
            if #available(iOS 16.0, *) {
                return windowScene?.interfaceOrientation.isPortrait ?? false
            }
            return UIDevice.current.orientation.isPortrait
        }
        
        var isFlat: Bool {
            if #available(iOS 16.0, *) {
                return false
            }
            return UIDevice.current.orientation.isFlat
        }
    }
    
    extension UIInterfaceOrientationMask {
        var toUIInterfaceOrientation: UIInterfaceOrientation {
            switch self {
            case .portrait:
                return UIInterfaceOrientation.portrait
            case .portraitUpsideDown:
                return UIInterfaceOrientation.portraitUpsideDown
            case .landscapeRight:
                return UIInterfaceOrientation.landscapeRight
            case .landscapeLeft:
                return UIInterfaceOrientation.landscapeLeft
            default:
                return UIInterfaceOrientation.unknown
            }
        }
    }
    

    How to use it:

     DeviceOrientation.shared.set(orientation: .portrait)
    
    Login or Signup to reply.
  7. Following Apple’s documentation you need to

    Requests an update to the window scene’s geometry using the specified geometry preferences object.

    https://developer.apple.com/documentation/uikit/uiwindowscene/3975944-requestgeometryupdate/

    So using the code in the example, you can change the way we set the orientation in our views using requestGeometryUpdate and using as well setNeedsUpdateOFSupportedInterface

    public extension UIViewController {
    
    func deviceOrientation(orientation: UIInterfaceOrientationMask) {
        if #available(iOS 16.0, *) {
            guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
            else { return }
            windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))
            self.setNeedsUpdateOfSupportedInterfaceOrientations()
        }
      }
    }
    
    Login or Signup to reply.
  8. I tried all above solutions seem they’re not 100% percent working. After through this post
    https://developer.apple.com/forums/thread/707735 i got the hint. Let’s try this below code. It’s worked for me.

    if #available(iOS 16.0, *) {
            DispatchQueue.main.async {
                UIViewController.attemptRotationToDeviceOrientation()
                    
                let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
                    windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation)) { error in
                    print(error)
                    print(windowScene?.effectiveGeometry)
                }
                   navigationController?.topViewController?.setNeedsUpdateOfSupportedInterfaceOrientations()
            }
       }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search