在 SwiftUI 视图中使用开关/枚举 [英] Using switch/enums in SwiftUI Views
问题描述
从 Xcode 11.4 开始,SwiftUI 不允许在诸如 VStack {}
之类的函数构建器块中使用 switch
语句,失败并出现诸如 Generic parameter 之类的一般错误内容'无法推断
.如何在 SwiftUI 中使用 switch
语句根据枚举值创建不同的视图?
As of Xcode 11.4, SwiftUI doesn't allow switch
statements in Function builder blocks like VStack {}
, failing with a generic error like Generic parameter 'Content' could not be inferred
. How can the switch
statement be used in SwiftUI to create different Views depending on an enum value?
推荐答案
switch
从 Xcode 12 开始支持 SwiftUI 视图构建器:
switch
in SwiftUI view builders is supported since Xcode 12:
enum Status {
case loggedIn, loggedOut, expired
}
struct SwiftUISwitchView: View {
@State var userStatus: Status = .loggedIn
var body: some View {
VStack {
switch self.userStatus {
case .loggedIn:
Text("Welcome!")
case .loggedOut:
Image(systemName: "person.fill")
case .expired:
Text("Session expired")
}
}
}
}
对于 Xcode 11,您可以使用以下解决方法:
For Xcode 11 you can use the following workarounds:
a) 将其包装在具有显式返回类型的单个 Group
块中 - 如果 switch 语句是函数构建器块中的唯一语句,则允许这样做:
a) Wrap it in a single Group
block with an explicit return type - this is allowed if the switch statement is the only statement in the function builder block:
enum Status {
case loggedIn, loggedOut, expired
}
struct SwiftUISwitchView: View {
@State var userStatus: Status = .loggedIn
var body: some View {
VStack {
Group { () -> Text in
switch(self.userStatus) {
case .loggedIn:
return Text("Welcome!")
case .loggedOut:
return Text("Please log in")
case .expired:
return Text("Session expired")
}
}
}
}
}
struct SwitchUsageInSwiftUI_Previews: PreviewProvider {
static var previews: some View {
SwiftUISwitchView()
}
}
替代方案 b) 创建一个单独的函数来根据枚举计算视图:
Alternative b) Create a separate function to compute the View based on the enum:
struct SwiftUISwitchView: View {
@State var userStatus: Status = .loggedIn
// if it's always the same View, you can use some View
func viewFor(status: Status) -> some View {
switch(status) {
case .loggedIn:
return Text("Welcome!")
case .loggedOut:
return Text("Please log in")
case .expired:
return Text("Session expired")
}
}
var body: some View {
VStack {
viewFor(status: userStatus)
}
}
}
如果返回的视图可以有不同的类型,则需要将其包装在一个 AnyView
中,因为 some View
要求在所有情况下返回类型都相同:
If the returned view can have different types, you need to wrap it in an AnyView
because some View
requires the return type to be the same in all cases:
// if it's different types, you have to erase to AnyView
func viewForStatusDifferentViews(status: Status) -> AnyView {
switch(status) {
case .loggedIn:
return AnyView(Text("Welcome!"))
case .loggedOut:
return AnyView(Image(systemName: "person.fill"))
case .expired:
return AnyView(Text("Session expired"))
}
}
替代方法 c) 创建一个单独的 View 以通过枚举值计算 View:
Alternative c) Create a separate View to compute the View by enum value:
// Alternative: A separate view
struct StatusView: View {
var status : Status
var body: some View {
switch(status) {
case .loggedIn:
return AnyView(Text("Welcome!"))
case .loggedOut:
return AnyView(Image(systemName: "person.fill"))
case .expired:
return AnyView(Text("Session expired"))
}
}
}
可在 Github 上运行的示例代码:SwiftUIPlayground
这篇关于在 SwiftUI 视图中使用开关/枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!