【问题标题】:SwiftUI Force Portrait On All Except One ViewSwiftUI 在除一个视图之外的所有视图上强制肖像
【发布时间】:2020-01-07 17:36:48
【问题描述】:

我有一个 SwiftUI 项目。对于除一个视图之外的所有视图,我想允许纵向和仅纵向模式。只有一个视图,我想同时允许纵向和横向。 Swift 上有一些资源,但我在 SwiftUI 上找不到。

有没有人找到办法做到这一点?

【问题讨论】:

    标签: ios orientation swiftui landscape portrait


    【解决方案1】:

    我不得不做类似的事情。这是我们的方法。

    我们将项目方向设置为仅支持纵向模式。

    然后在您的AppDelegate 中添加一个实例变量用于方向并符合supportedInterfaceOrientationsFor 委托方法。

    static var orientationLock = UIInterfaceOrientationMask.portrait
    
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return AppDelegate.orientationLock
    }
    

    然后,当您要呈现横向视图时,请执行以下操作:

    AppDelegate.orientationLock = UIInterfaceOrientationMask.landscapeLeft
    UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
    UIViewController.attemptRotationToDeviceOrientation()
    

    在解雇时,

    AppDelegate.orientationLock = UIInterfaceOrientationMask.portrait
    UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
    UIViewController.attemptRotationToDeviceOrientation()
    

    希望这会有所帮助!

    【讨论】:

    • 非常感谢!尝试执行 UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft, forKey: "orientation") 时出现错误,但我真的不需要那部分。第一行就是我所需要的。
    • 这只是将设备锁定为横向模式,但 OP 要求允许纵向和横向视图。是否有解决方案可以在此视图中同时允许纵向和横向?
    • 我收到一个错误:*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__SwiftValue longLongValue]: unrecognized selector sent to instance 0x282de73c0' 有什么想法吗?
    • 为了不出错,你必须把 DispatchQueue.main.async 放在 onAppear 和 onDisappear 方法中。
    • 是的,它只是工作,感谢这个伟大的解决方案。奖励:它也适用于 iOS 14。我知道应该这样做,但是当我难以置信地盯着我在 Xcode 12 和 iOS 14 上损坏的应用程序(在 iOS 13 下运行良好)时,我的许多确定性都被打破了......所以至少这是可行的。跨度>
    【解决方案2】:

    对上述答案的一些调整:

    在 AppDelegate 作为上面乔纳森的回答:

    static var orientationLock = 
    UIInterfaceOrientationMask.portrait
    
    func application(_ application: UIApplication, 
    supportedInterfaceOrientationsFor window: 
    UIWindow?) -> UIInterfaceOrientationMask {
    return AppDelegate.orientationLock
    }
    

    然后在“destinationView”中 - 风景:

    import SwiftUI
    
    struct DestinationView: View {
    
    var body: some View {
        Group {
    
            Text("Hello")
    
        }.onAppear {
            AppDelegate.orientationLock = UIInterfaceOrientationMask.landscapeLeft
            UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
            UINavigationController.attemptRotationToDeviceOrientation()
        }
        .onDisappear {
            DispatchQueue.main.async {
                AppDelegate.orientationLock = UIInterfaceOrientationMask.portrait
                UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
                UINavigationController.attemptRotationToDeviceOrientation()
            }
        }
    }
    }
    

    注意 UIDevice 行中的 .rawValue 消除了“LongValue”错误。此外,在 .onDisappear 中,我必须使用 DispatchQueue.main.async 以避免在返回到纵向视图时出现错误。

    【讨论】:

    • Zenman 的回答太好了!简单,直接,并且“有效”。感谢您弄清楚这一点。为让这件事变得如此困难而感到羞耻。
    • 我用过同样的东西。非常感谢@Zenman C 与我所面临的情况有所不同。我还必须将 onAppear 部分包装在 DispatchQueue.main.async 中。
    • 如果我想要 LandscapeLeft 和 LandscapeRight,我需要做什么?
    • 由于某种原因,这在我进入视图的前几次不起作用,突然进出几次后它开始工作,然后它继续工作。很奇怪。我也确实将调用添加到主队列。
    • 事实证明,如果我没有从 Xcode 运行它到连接了调试器的设备,它工作正常。以防其他人遇到此问题。尝试断开手机,然后在设备上运行它。
    【解决方案3】:

    如果您的应用使用 SwiftUI lifeCycle,则应用会使用符合 App 协议的自定义结构启动。您的应用没有实现上述解决方案所需的 AppDelegate。

    要制作您自己的 AppDelegate,请在您的 appnameApp.swift 中尝试此代码

    @main
    struct appnameApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
        var body: some Scene {
            WindowGroup {
                ContentView()
            }
        }
    }
    
    class AppDelegate: NSObject, UIApplicationDelegate {
        
        static var orientationLock = UIInterfaceOrientationMask.portrait
        
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
            // something to do
            return true
        }
        
        func application(_ application: UIApplication, supportedInterfaceOrientationsFor window:UIWindow?) -> UIInterfaceOrientationMask {
            return AppDelegate.orientationLock
        }
    }
    

    来源:https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-appdelegate-to-a-swiftui-app

    【讨论】:

      【解决方案4】:

      使用来自https://stackoverflow.com/a/41811798/10330141的AppUtility

      在 SwiftUI 中

      创建自定义 UIHostingController

       class OrientationHostingController : UIHostingController<AnyView> {
          
          override func viewWillAppear(_ animated: Bool) {
              super.viewWillAppear(animated)
              
              AppUtility.lockOrientation(.portrait)
              
          }
       }
      
      
      
      
      let rootView = OrientationHostingController(rootView: AnyView(SwiftUIView()))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-04
        • 2013-11-28
        • 1970-01-01
        • 1970-01-01
        • 2021-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多