swiftxcodeios16xcode14swift5.7

iOS16+ Present UIViewController in landscape only for single screen not working [Swift 5.7]


Before iOS 16 presenting a single screen in landscape is fine for portrait application. The working code is as below.

Remark: Whole application is in Portrait mode only.

override public var shouldAutorotate: Bool {
    return false
}

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .landscapeLeft
}

override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .landscapeLeft
}

I found the solution but it's for UIWindowScene but I need solution in UIWindow. I need help to fix it in iOS 16.

Xcode - 14.0, iOS - 16.0, Simulator - 14 Pro

I can prepare demo if anyone needs.


Solution

  • After many tries I came up with the simple solution. As I mentioned in the question my whole app is in portrait mode only and only one screen that I want to present in the landscape.

    This code doesn't required any external window to be makeKeyAndVisible. If you use extra window to present then you need to write to dismiss separately for iOS 16.

    Old code which was working in previous versions of iOS 16 will be remain same and no change in it.

    Magic lines are as below.

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        if let _ = window?.rootViewController?.presentedViewController as? LandscapeChartVC {
            if #available(iOS 16.0, *) {
                return .landscapeLeft
            } else {
                return .portrait
            }
        } else {
            return .portrait
        }
    }
    

    I've identified my landscape view controller in the appDelegate's supportedInterfaceOrientationsFor.

    Well you can change word presentedViewController to get your controller. And that's it.

    Add support with iPad for all 3 or 4 orientation with this:

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        if UIDevice.IS_IPAD {
            return .allButUpsideDown
        } else {
            if let _ = window?.rootViewController?.presentedViewController as? LandscapeChartVC {
                if #available(iOS 16.0, *) {
                    return .landscapeLeft
                } else {
                    return .portrait
                }
            } else {
                return .portrait
            }
        }
    

    If requirement for iPad app to lock the orientations you can follow iPhone / above code.

    This idea come up with answers and thank you everyone who shared interest. If anyone still get more improved solution I'll happy to update.