如何在SwiftUI中检测目标环境是否为iPadOS?

27

我希望在构建iOS和iPadOS时显示不同的视图。目前,我知道我可以这样做:

import SwiftUI

struct ContentView: View {
    #if targetEnvironment(macCatalyst)
    var body: some View {
        Text("Hello")
    }
    #else
    var body: some View {
        Text("Hello")
    }
    #endif
}

为了在 macOS 和 iPadOS/iOS 之间显示不同的视图(在 Swift 4/5 中引入),但是我该如何区分后者?我似乎无法使用 targetEnvironment...

4个回答

29

我在我的代码中使用了这个:

    private var idiom : UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
    private var isPortrait : Bool { UIDevice.current.orientation.isPortrait }

那么你可以这样做:

    var body: some View {
        NavigationView {
            masterView()

            if isPortrait {
                portraitDetailView()
            } else {
                landscapeDetailView()
            }
        }
    }

    private func portraitDetailView() -> some View {
        if idiom == .pad {
            return Text("iPadOS")
        } else {
            return Text("iOS")
        }
    }

是的,private var idiom: UIUserInterfaceIdiom {UIDevice.current.userInterfaceIdiom} 是我找到的最佳解决方案。谢谢。 - undefined

21

我将以下代码作为UIDevice的扩展添加:

extension UIDevice {
    static var isIPad: Bool {
        UIDevice.current.userInterfaceIdiom == .pad
    }
    
    static var isIPhone: Bool {
        UIDevice.current.userInterfaceIdiom == .phone
    }
}

现在我可以调用UIDevice.isIPadUIDevice.isIPhone来知道是哪种设备。


我更喜欢这个解决方案,但我认为它应该被用作UIDevice.current.isIpad和UIDevice.current.isIphone。至少这就是我必须编写它才能工作的方式。 - johnnelm9r

6

要返回不同的视图类型,您可以使用 AnyView 擦除器类型:

if UIDevice.current.userInterfaceIdiom == .pad {
    return AnyView(Text("Hello, World!"))
} else {
    return AnyView(Rectangle().background(Color.green))
}

2
虽然你可以直接检查设备类型,就像其他答案建议的那样,但最佳实践是使用水平和/或垂直的size classes。定义视图布局的约束通常是视图的大小,而不是设备本身,因此这些API允许我们更语义化地声明我们的意图。
这样做还可以为你的应用程序提供对split view等功能的自然支持。
struct ContentView: View {

    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    
    var body: some View {
        // or use verticalSizeClass if you want to consider view height
        // or use both!
        if horizontalSizeClass == .compact {
            compactView
        } else {
            regularView
        }
    }

    private var regularView: some View {
        Text("Regular")
    }

    private var compactView: some View {
        Text("Compact")
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接