SwiftUI:用于通用(macOS 和 iOS)视图的 UserInterfaceSizeClass
SwiftUI: UserInterfaceSizeClass for Universal (macOS & iOS) Views
尝试在 macOS(本机,而非 Catalyst)上引用 @Environment
对象 horizontalSizeClass
和 verticalSizeClass
会导致以下错误:
'horizontalSizeClass' is unavailable in macOS
'verticalSizeClass' is unavailable in macOS
我明白这些属性并不真正适用于 macOS,但这对创建通用的 SwiftUI 视图(即跨 macOS 的跨平台,iOS 等)构成了很大障碍。
一种解决方法是将所有大小为 class 的特定代码包装在条件编译中,但结果是大量重复和冗余(参见下面的示例)。
有没有更有效的方法来处理这个问题?
通用视图示例:
struct ExampleView: View {
#if !os(macOS)
@Environment(\.horizontalSizeClass) var horizontalSizeClass
#endif
private var item1: some View {
Text("Example Item 1")
}
private var item2: some View {
Text("Example Item 2")
}
private var item3: some View {
Text("Example Item 3")
}
var body: some View {
VStack {
#if !os(macOS)
if horizontalSizeClass == .compact {
VStack {
item1
item2
item3
}
} else {
HStack {
item1
item2
item3
}
}
#else
HStack {
item1
item2
item3
}
#endif
}
}
}
确实 macOS 本身不支持 horizontalSizeClass
和 verticalSizeClass
,但好消息是添加它们很容易。
您可以定义自己的 @Environment
对象,方法是创建一个符合 EnvironmentKey
的 struct
,然后使用它来扩展 EnvironmentValues
。
在 macOS 上实现大小 类 所需的全部内容如下。它们始终只是 return .regular
,但足以发挥与 iOS.
完全相同的功能
#if os(macOS)
enum UserInterfaceSizeClass {
case compact
case regular
}
struct HorizontalSizeClassEnvironmentKey: EnvironmentKey {
static let defaultValue: UserInterfaceSizeClass = .regular
}
struct VerticalSizeClassEnvironmentKey: EnvironmentKey {
static let defaultValue: UserInterfaceSizeClass = .regular
}
extension EnvironmentValues {
var horizontalSizeClass: UserInterfaceSizeClass {
get { return self[HorizontalSizeClassEnvironmentKey] }
set { self[HorizontalSizeClassEnvironmentKey] = newValue }
}
var verticalSizeClass: UserInterfaceSizeClass {
get { return self[VerticalSizeClassEnvironmentKey] }
set { self[VerticalSizeClassEnvironmentKey] = newValue }
}
}
#endif
有了这个,您不需要为 macOS 做任何特殊的事情。例如:
struct ExampleView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
private var item1: some View {
Text("Example Item 1")
}
private var item2: some View {
Text("Example Item 2")
}
private var item3: some View {
Text("Example Item 3")
}
var body: some View {
VStack {
if horizontalSizeClass == .compact {
VStack {
item1
item2
item3
}
} else {
HStack {
item1
item2
item3
}
}
}
}
}
您甚至可以将这些扩展放入一个框架中以便更广泛地使用,只要您将它们定义为 public
。
尝试在 macOS(本机,而非 Catalyst)上引用 @Environment
对象 horizontalSizeClass
和 verticalSizeClass
会导致以下错误:
'horizontalSizeClass' is unavailable in macOS
'verticalSizeClass' is unavailable in macOS
我明白这些属性并不真正适用于 macOS,但这对创建通用的 SwiftUI 视图(即跨 macOS 的跨平台,iOS 等)构成了很大障碍。
一种解决方法是将所有大小为 class 的特定代码包装在条件编译中,但结果是大量重复和冗余(参见下面的示例)。
有没有更有效的方法来处理这个问题?
通用视图示例:
struct ExampleView: View {
#if !os(macOS)
@Environment(\.horizontalSizeClass) var horizontalSizeClass
#endif
private var item1: some View {
Text("Example Item 1")
}
private var item2: some View {
Text("Example Item 2")
}
private var item3: some View {
Text("Example Item 3")
}
var body: some View {
VStack {
#if !os(macOS)
if horizontalSizeClass == .compact {
VStack {
item1
item2
item3
}
} else {
HStack {
item1
item2
item3
}
}
#else
HStack {
item1
item2
item3
}
#endif
}
}
}
确实 macOS 本身不支持 horizontalSizeClass
和 verticalSizeClass
,但好消息是添加它们很容易。
您可以定义自己的 @Environment
对象,方法是创建一个符合 EnvironmentKey
的 struct
,然后使用它来扩展 EnvironmentValues
。
在 macOS 上实现大小 类 所需的全部内容如下。它们始终只是 return .regular
,但足以发挥与 iOS.
#if os(macOS)
enum UserInterfaceSizeClass {
case compact
case regular
}
struct HorizontalSizeClassEnvironmentKey: EnvironmentKey {
static let defaultValue: UserInterfaceSizeClass = .regular
}
struct VerticalSizeClassEnvironmentKey: EnvironmentKey {
static let defaultValue: UserInterfaceSizeClass = .regular
}
extension EnvironmentValues {
var horizontalSizeClass: UserInterfaceSizeClass {
get { return self[HorizontalSizeClassEnvironmentKey] }
set { self[HorizontalSizeClassEnvironmentKey] = newValue }
}
var verticalSizeClass: UserInterfaceSizeClass {
get { return self[VerticalSizeClassEnvironmentKey] }
set { self[VerticalSizeClassEnvironmentKey] = newValue }
}
}
#endif
有了这个,您不需要为 macOS 做任何特殊的事情。例如:
struct ExampleView: View {
@Environment(\.horizontalSizeClass) var horizontalSizeClass
private var item1: some View {
Text("Example Item 1")
}
private var item2: some View {
Text("Example Item 2")
}
private var item3: some View {
Text("Example Item 3")
}
var body: some View {
VStack {
if horizontalSizeClass == .compact {
VStack {
item1
item2
item3
}
} else {
HStack {
item1
item2
item3
}
}
}
}
}
您甚至可以将这些扩展放入一个框架中以便更广泛地使用,只要您将它们定义为 public
。