iOS 16 Scene orientation issue
Asked Answered
A

5

15

I always received this error when I tried to allowed only portrait orientation on my controller: Error Domain=UISceneErrorDomain Code=101 "None of the requested orientations are supported by the view controller. Requested: landscapeLeft; Supported: portrait" UserInfo={NSLocalizedDescription=None of the requested orientations are supported by the view controller. Requested: landscapeLeft; Supported: portrait}

I called this method:

func updateOrientation(orientation: UIInterfaceOrientationMask) {
        if #available(iOS 16, *) {
            DispatchQueue.main.async {
                let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
                self.setNeedsUpdateOfSupportedInterfaceOrientations()
                self.navigationController?.setNeedsUpdateOfSupportedInterfaceOrientations()
                windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation)) { error in
                    print(error)
                    print(windowScene?.effectiveGeometry )
                }
            }
        }
    }

Did someone face the same issue ?

Anthracene answered 8/9, 2022 at 13:6 Comment(1)
Maybe this is relevant? developer.apple.com/forums/thread/707735Mandarin
V
2

J.Y.527 found a solution : https://mcmap.net/q/162138/-is-force-view-controller-orientation-working-in-ios-16-beta

It looks like a workaround, but it's fixed the problem in my case.

the trick is to update the AppDelegate supported orientation when you need to rotate.

In Your AppDelegate :

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

Then in your controller :

 static func SwitchOrientation(orientation : UIInterfaceOrientationMask, viewController : UIViewController){
 
    
    
    if #available(iOS 16.0, *) {
        (UIApplication.shared.delegate as? AppDelegate)?.orientation = orientation
                            
        let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
        windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))

        UIApplication.navigationTopViewController()?.setNeedsUpdateOfSupportedInterfaceOrientations()
        
        DispatchQueue.main.async {
                    let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
                    viewController.setNeedsUpdateOfSupportedInterfaceOrientations()
                    viewController.navigationController?.setNeedsUpdateOfSupportedInterfaceOrientations()
                    windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation)) { error in
                        print(error)
                        print(windowScene?.effectiveGeometry ?? "")
                    }
                }
    

    } else{
        UIDevice.current.setValue(orientation, forKey: "orientation")
    }
  
}
Vtehsta answered 28/9, 2022 at 13:5 Comment(1)
hi @Jeffrey, could you please provide how to define the function for orientation in AppDelegate.m file as i'm getting the error Value of AppDelegate has no member 'orientation' inspite of defining something like this which OrrHsiao has mentioned below (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { return UIInterfaceOrientationMaskAll; }. Could you please advise me.Cockfight
F
1

You can try like this, it work for me

- (void)forceOrientation:(UIDeviceOrientation)orientation {
    if (@available(iOS 16.0, *)) {
        UIInterfaceOrientationMask orientationMask = (1 << orientation);
        [self setNeedsUpdateOfSupportedInterfaceOrientations];
        UIWindowScene *windowScene = (UIWindowScene *) 
        [UIApplication sharedApplication].connectedScenes.allObjects.firstObject;
        for (UIWindow *windows in windowScene.windows) {
            [windows.rootViewController setNeedsUpdateOfSupportedInterfaceOrientations];
        }
        UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:orientationMask];
        [windowScene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:nil];
    } else {
       [[UIDevice currentDevice] setValue:@(orientation) forKey:@"orientation"];
       [UIViewController attemptRotationToDeviceOrientation];
    }
}
Furmenty answered 23/3, 2023 at 9:17 Comment(1)
Iterating through windowScene.windows, worked for me. ThanksDisordered
C
1

Here is the best and easy solution that works in all iOS version including iOS 16+.

Initially set the orientation value on AppDelegate as here I am forcing app to only one orientation

var orientationLock = UIInterfaceOrientationMask.portrait

and function as

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

then you can make an extension class of UIViewController as

 extension UIViewController {

    /// Lock your orientation
    func lockOrientation(_ orientation: UIInterfaceOrientationMask) {

        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationLock = orientation
        }

        if #available(iOS 16.0, *) {
            self.setNeedsUpdateOfSupportedInterfaceOrientations()
        }
    }

    /// OPTIONAL Added method to adjust lock and rotate to the desired orientation
    func lockOrientation(
        _ allowOrientation: UIInterfaceOrientationMask,
        andRotateTo rotateOrientation: UIInterfaceOrientationMask) {
            
        self.lockOrientation(allowOrientation)

        if #available(iOS 16.0, *) {
            UIViewController.attemptRotationToDeviceOrientation()
            let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
            windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: rotateOrientation))

            self.setNeedsUpdateOfSupportedInterfaceOrientations()

        } else {

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

you can call the method from your controller to enable which orientation you want. Here, I put all orientation.

        self.lockOrientation(.all)

And If you want to forcefully change orientation of the view controller which locking orientation then call as from your ViewController

    self.lockOrientation(.all, andRotateTo: .portrait)

Here, I am locking my orientation to all and forcing to change to portrait.

Good luck!!!

Cryptograph answered 25/5, 2023 at 6:0 Comment(3)
Hey, thanks! That works quite well for me on iOS 16.4. I'm seeing this warning that UIViewController.attemptRotationToDeviceOrientation() has been deprecated in iOS 16+, so should it go down into the else case instead? Don't have a setup for testing that yet. Will try tomorrowBienne
@Bienne It's working on my case. If anything happen please let me know.Cryptograph
Did not work for mePanegyrize
S
0

Yes, I faced the same issue and resolved it as below. Provided error clearly saying that we are trying to rotate the device where we are restricting it to use only in one mode previously somewhere in the app. In my case I was implemented below method in Appdelegate.swift

var myOrientation: UIInterfaceOrientationMask = .portrait

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

so restricting it to only use the portrait mode, caused to fail the rotation of the app in landscape mode.

By changing the orientation to all, makes it work.

var myOrientation: UIInterfaceOrientationMask = .portrait
Sandman answered 21/9, 2022 at 17:14 Comment(0)
C
-1

try it in Appdelegate

  • (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { return UIInterfaceOrientationMaskAll; }
Cassandracassandre answered 15/9, 2022 at 15:4 Comment(2)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Whiteside
@Cassandracassandre I'm facing the same issue where I included what you mentioned for UIInterOrientationMask function in AppDelegate.m and have included the implementation as provided by Jeffrey in a separate function in .swift file, but i get the compiler error "Value of type 'AppDelegate' has no member 'orientation' ". I'm from RN background and new to obj-c and swift. Could you please advise me as i'm in a dire need of it.Cockfight

© 2022 - 2025 — McMap. All rights reserved.