I have a SwiftUI iPhone-only app with its orientation locked in portrait, which works great. However, when the same app is run on an iPad (in emulation mode; iPad is not a target) the lock has no effect: the UI rotates with the device, which is unintended as it breaks the UI. It fails in the simulator and on an actual device.
I can reproduce this issue using an empty SwiftUI project with only a single view:
struct ContentView: View {
var body: some View {
Text("Hello, world!")
}
}
iPhone works as expected:
iPad does not respect orientation lock:
I have the following in my Info.plist, but no success. The UI still rotates on the iPad.
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
Then I defined an AppDelegate. Still no success, the UI keeps rotating on the iPad.
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.portrait
}
}
@main
struct orientationApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
What is interesting:
- When I enable iPad as a target the orientation lock works out of the box. However, I do not want to offer the app for the iPad. I just want to fix the UI for users who deliberately install iPhone apps on their iPad.
- When I test the AppDelegate approach on an iPhone it works even if I allow all device orientations in Info.plist, so it seems to do the right thing (just not on the iPad).
I'm using Xcode 12.5 and Swift 5.