我正在尝试使用苹果多年来已经贬值的一堆方法来锁定我的应用程序的轮换,但我不知所措。
使用 SwiftUI 的 Xcode 项目中不再存在 SceneDelegate 或 AppDelegate,这意味着我无法使用人们提出的任何先前方法并在 SwiftUI 中编写解决方案:How do I lock a certain View in Portrait mode while允许其他人改变方向?。当我尝试在我的程序中实现此解决方案时,Xcode 返回警告
BUG IN CLIENT OF UIKIT: Setting UIDevice.orientation is not supported. Please use UIWindowScene.requestGeometryUpdate(_:)
这是我当前的代码
import SwiftUI
struct ContentView: View {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some View {
ZStack {
// rest of code is here
}
}.onAppear {
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation") // Forcing the rotation to portrait
AppDelegate.orientationLock = .portrait // And making sure it stays that way
}
}
class AppDelegate: NSObject, UIApplicationDelegate {
static var orientationLock = UIInterfaceOrientationMask.all
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return AppDelegate.orientationLock
}
}
对于支持不同方向的 SwiftUI 应用程序,您可以通过挖掘
UIWindowScene
并请求几何更新来请求特定方向,例如在 .onAppear
回调中(需要 iOS 16):
.onAppear {
if #available(iOS 16.0, *) {
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
scene.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait)) { error in
// Handle denial of request.
}
}
}
}
即使离开视图,方向也将保持这种状态。因此,要让它回到当前的物理方向,您也可以添加一个
.onDisappear
回调:
.onDisappear {
if #available(iOS 16.0, *) {
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
scene.requestGeometryUpdate(.iOS(interfaceOrientations: .all))
}
}
}
如果用户在视图出现后切换物理设备方向,则物理方向生效。要覆盖此设置,您可以使用
GeometryReader
来测量屏幕尺寸并添加 .onChange
来响应更改:
private func requestOrientations(_ orientations: UIInterfaceOrientationMask) {
if #available(iOS 16.0, *) {
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
scene.requestGeometryUpdate(.iOS(interfaceOrientations: orientations)) { error in
// Handle denial of request.
}
}
}
}
var body: some View {
GeometryReader { proxy in
MyPortraitView()
.onAppear {
requestOrientations(.portrait)
}
.onChange(of: proxy.size) {
requestOrientations(.portrait)
}
.onDisppear {
requestOrientations(.all)
}
}
}
请注意,视图方向的更改是动画的,因此如果使用
.onChange
覆盖物理方向的更改,则用户体验不会那么好。