首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在SwiftUI视图中使用开关/枚举

在SwiftUI视图中使用开关/枚举
EN

Stack Overflow用户
提问于 2020-05-17 00:07:19
回答 2查看 2.4K关注 0票数 1

从Xcode11.4开始,SwiftUI不允许在像VStack {}这样的函数构造器块中使用switch语句,失败时会出现像Generic parameter 'Content' could not be inferred这样的通用错误。如何在SwiftUI中使用switch语句根据枚举值创建不同的视图?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-17 00:07:19

从Xcode12开始支持SwiftUI视图构建器中的switch

代码语言:javascript
复制
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,您可以使用以下解决方法:

a)使用显式返回类型将其包装在单个Group块中-如果switch语句是函数构建器块中的唯一语句,则允许这样做:

代码语言:javascript
复制
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)创建一个单独的函数来根据枚举计算View:

代码语言:javascript
复制
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要求返回类型在所有情况下都相同:

代码语言:javascript
复制
// 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 by enum值:

代码语言:javascript
复制
// 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"))
        }
    }
    
}

Runnable example code at Github: SwiftUIPlayground

票数 8
EN

Stack Overflow用户

发布于 2021-04-10 04:56:34

您可以将枚举与@ViewBuilder一起使用,如下所示...

Declear枚举

代码语言:javascript
复制
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"
    }
  }
  
}

现在在视图文件中

代码语言:javascript
复制
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使用相同的大小写...您可以使用它,如下所示

代码语言:javascript
复制
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()
    }
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61839742

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档