在SwiftUI视图中使用开关/枚举
从Xcode 11.4开始,SwiftUI不允许在函数生成器块(如VStack{})中使用switch语句,失败时出现一般错误,如无法推断一般参数“Content”。如何在SwiftUI中使用switch语句根据枚举值创建不同的视图?SwiftUI视图生成器中的switch受支持,因为Xcode 12: 枚举状态{ 案例日志数据,日志数据,过期 } 结构SwiftUISwitchView:视图{ @状态变量userStatus:Status=.loggedIn var body:一些观点{ VStack{ 切换self.userStatus{ 案例:loggedIn: 欢迎! 案例。loggedOut: ImagesystemName:person.fill 案例。过期: 文本会话已过期 } } } } 对于Xcode 11,您可以使用以下变通方法: 将其包装在具有显式返回类型的单个组块中-如果switch语句是function builder块中的唯一语句,则允许此操作: 枚举状态{ 案例日志数据,日志数据,过期 } 结构SwiftUISwitchView:视图{ @状态变量userStatus:Status=.loggedIn var body:一些观点{ VStack{ 组{->中的文本 switchself.userStatus{ 案例:loggedIn: 欢迎回来! 案例。loggedOut: 返回文本请登录 案例。过期: 返回文本会话已过期 } } } } } 结构SwitchUsageInSwiftUI\u预览:PreviewProvider{ 静态var预览:一些视图{ 迅捷视图 } } 备选方案b创建一个单独的函数以基于枚举计算视图: 结构SwiftUISwitchView:视图{ @状态变量userStatus:Status=.loggedIn //如果始终是同一视图,则可以使用某些视图 func viewForstatus:状态->某些视图{ 开关状态{ 案例:loggedIn: 欢迎回来! 案例。loggedOut: 返回文本请登录 案例。过期: 返回文本会话已过期 } } var body:一些观点{ VStack{ viewForstatus:userStatus } } } 如果返回的视图可以有不同的类型,则需要将其包装在AnyView中,因为某些视图要求返回类型在所有情况下都相同:在SwiftUI视图中使用开关/枚举,swiftui,Swiftui,从Xcode 11.4开始,SwiftUI不允许在函数生成器块(如VStack{})中使用switch语句,失败时出现一般错误,如无法推断一般参数“Content”。如何在SwiftUI中使用switch语句根据枚举值创建不同的视图?SwiftUI视图生成器中的switch受支持,因为Xcode 12: 枚举状态{ 案例日志数据,日志数据,过期 } 结构SwiftUISwitchView:视图{ @状态变量userStatus:Status=.loggedIn var body:一些观点{ VS
// 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创建一个单独的视图以按枚举值计算视图:
//备选方案:一个单独的视图
结构状态视图:视图{
变量状态:状态
var body:一些观点{
开关状态{
案例:loggedIn:
返回任意ViewTextWelcome!
案例。loggedOut:
返回AnyViewImagesystemName:person.fill
案例。过期:
返回任何已过期的ViewTextSession
}
}
}
自Xcode 12以来,支持SwiftUI视图生成器中的切换:
枚举状态{
案例日志数据,日志数据,过期
}
结构SwiftUISwitchView:视图{
@状态变量userStatus:Status=.loggedIn
var body:一些观点{
VStack{
切换self.userStatus{
案例:loggedIn:
欢迎!
案例。loggedOut:
ImagesystemName:person.fill
案例。过期:
文本会话已过期
}
}
}
}
对于Xcode 11,您可以使用以下变通方法:
将其包装在具有显式返回类型的单个组块中-如果switch语句是function builder块中的唯一语句,则允许此操作:
枚举状态{
案例日志数据,日志数据,过期
}
结构SwiftUISwitchView:视图{
@状态变量userStatus:Status=.loggedIn
var body:一些观点{
VStack{
组{->中的文本
switchself.userStatus{
案例:loggedIn:
欢迎回来!
案例。loggedOut:
返回文本请登录
案例。过期:
返回文本会话已过期
}
}
}
}
}
结构SwitchUsageInSwiftUI\u预览:PreviewProvider{
静态var预览:一些视图{
迅捷视图
}
}
备选方案b创建一个单独的函数以基于枚举计算视图:
结构SwiftUISwitchView:视图{
@状态变量userStatus:Status=.loggedIn
//如果始终是同一视图,则可以使用某些视图
func viewForstatus:状态->某些视图{
开关状态{
案例:loggedIn:
欢迎回来!
案例。loggedOut:
返回文本请登录
案例。过期:
返回文本会话已过期
}
}
var body:一些观点{
VStack{
viewForstatus:userStatus
}
}
}
如果返回的视图可以有不同的类型,则需要将其包装在AnyView中,因为某些视图需要
返回类型在所有情况下都相同:
// 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创建一个单独的视图以按枚举值计算视图:
//备选方案:一个单独的视图
结构状态视图:视图{
变量状态:状态
var body:一些观点{
开关状态{
案例:loggedIn:
返回任意ViewTextWelcome!
案例。loggedOut:
返回AnyViewImagesystemName:person.fill
案例。过期:
返回任何已过期的ViewTextSession
}
}
}
您可以将枚举与@ViewBuilder一起使用,如下所示
去垢枚举
enum Destination: CaseIterable, Identifiable {
case restaurants
case profile
var id: String { return title }
var title: String {
switch self {
case .restaurants: return "Restaurants"
case .profile: return "Profile"
}
}
}
现在在视图文件中
struct ContentView: View {
@State private var selectedDestination: Destination? = .restaurants
var body: some View {
NavigationView {
view(for: selectedDestination)
}
}
@ViewBuilder
func view(for destination: Destination?) -> some View {
switch destination {
case .some(.restaurants):
CategoriesView()
case .some(.profile):
ProfileView()
default:
EmptyView()
}
}
}
如果您想对NavigationLink使用相同的案例。。。您可以按如下方式使用它
struct ContentView: View {
@State private var selectedDestination: Destination? = .restaurants
var body: some View {
NavigationView {
List(Destination.allCases,
selection: $selectedDestination) { item in
NavigationLink(destination: view(for: selectedDestination),
tag: item,
selection: $selectedDestination) {
Text(item.title).tag(item)
}
}
}
}
@ViewBuilder
func view(for destination: Destination?) -> some View {
switch destination {
case .some(.restaurants):
CategoriesView()
case .some(.profile):
ProfileView()
default:
EmptyView()
}
}
}
您可以将枚举与@ViewBuilder一起使用,如下所示
去垢枚举
enum Destination: CaseIterable, Identifiable {
case restaurants
case profile
var id: String { return title }
var title: String {
switch self {
case .restaurants: return "Restaurants"
case .profile: return "Profile"
}
}
}
现在在视图文件中
struct ContentView: View {
@State private var selectedDestination: Destination? = .restaurants
var body: some View {
NavigationView {
view(for: selectedDestination)
}
}
@ViewBuilder
func view(for destination: Destination?) -> some View {
switch destination {
case .some(.restaurants):
CategoriesView()
case .some(.profile):
ProfileView()
default:
EmptyView()
}
}
}
如果您想对NavigationLink使用相同的案例。。。您可以按如下方式使用它
struct ContentView: View {
@State private var selectedDestination: Destination? = .restaurants
var body: some View {
NavigationView {
List(Destination.allCases,
selection: $selectedDestination) { item in
NavigationLink(destination: view(for: selectedDestination),
tag: item,
selection: $selectedDestination) {
Text(item.title).tag(item)
}
}
}
}
@ViewBuilder
func view(for destination: Destination?) -> some View {
switch destination {
case .some(.restaurants):
CategoriesView()
case .some(.profile):
ProfileView()
default:
EmptyView()
}
}
}