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.
5
Answers
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.
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:
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.
I found some related things in iOS 16 Release Notes.
https://developer.apple.com/documentation/ios-ipados-release-notes/ios-16-release-notes?changes=lat__8_1
There are some deprecations in UIKit:
I think you may have to use setNeedsUpdateOfSupportedInterface.
this can be done in two ways.
1 .personally I prefer this way
1.1 keep this function in AppDelegate to handle the orientation(this is must)
1.2 in which ViewController you want the force orientation, go to that view controller and add these lines in the variable declaring section
we will be updating the forceLandscape so it will get updated, then the supportedInterfaceOrientations also will get updated
1.3 Here we are setting the trigger for updating the forceLandscape (we can add these lines of code inside button action for handling IOS 16 force roatation)
this will update the forceLandscape, so it will check the orientation and update according to it
Above lines of code is for one way, another way is given below
2. Another way is updating orientation in AppDelegate class:
2.1 keep this function and property in AppDelegate to handle the orientation(this is must)
2.2 In the viewcontroller button action we can update the propperty
The best workaround for presenting modal view controller from portrait in landscape I managed to come up with is combination of
setNeedsUpdateOfSupportedInterfaceOrientations()
,requestGeometryUpdate(.iOS(interfaceOrientations: .landscape))
and allowed interface orientation on AppDelegate on a new window.AppDelegate:
Presenting view controller in landscape
Then when you want to dismiss it you need to
It’s still not 100% because the view controller is presented in landscape, then flicks back to portrait, and then again rotates to landscape after a second. But without the UIWindow it sometimes does this 2x before it locks in the landscape mode.
The
ViewController
I want to lock is inside aUINaviationController
. For this scenario here’s my working solutionI have this
struct
which has alock
andunlock
method.Prior to ios16 you only needed to call these two methods.
As of ios16 you now need to call
setNeedsUpdateOfSupportedInterfaceOrientations()
as well