【问题标题】:SwiftUI navigate to different view from ListSwiftUI 从 List 导航到不同的视图
【发布时间】:2020-07-26 01:18:59
【问题描述】:

我有一个使用 SwiftUI List 显示的菜单。下图示例:

我想要做的是将 NavigationLink 与不同的目标视图一起使用。我尝试在 List 块中使用 switch 语句,但 Xcode 抛出错误:

Closure containing control flow statement cannot be used with function builder 'ViewBuilder'

下面是我的代码:

struct HomeView: View {

    enum MenuItem: String, CaseIterable, Identifiable {
        var id : MenuItem {
            self
        }

        case firstCase = "Staff"
        case secondCase = "Projects"
        case thirdCase = "Invoices"
    }

    var body: some View {
        NavigationView {
            List(MenuItem.allCases) { itemText in

               switch itemText {
               case .firstCase:
                   NavigationLink(destination: StaffDetail()) {
                       HomeMenuRow(itemText: itemText)
                   }
                   break
               case .secondCase:
                   NavigationLink(destination: ProjectsDetail()) {
                       HomeMenuRow(itemText: itemText)
                   }
                   break

               case .thirdCase:
                   NavigationLink(destination: InvoicesDetail()) {
                       HomeMenuRow(itemText: itemText)
                   }
                   break
               }

            }
            .navigationBarTitle(Text("Menu"))
        }
    }
}

似乎找到了一些解决方案here,但不确定如何在List 对象中使用它。

【问题讨论】:

  • 看起来我发现我需要通过内部工厂方法函数调用此类代码。我说的对吗?
  • 您需要将您的逻辑移到body 之外,然后调用一个函数,然后返回您需要的内容。

标签: swift swiftui swift5


【解决方案1】:

试试这个:

struct StaffDetail : View  {
    var body: some View {
        Text("1")
    }
}

struct ProjectsDetail : View  {
    var body: some View {
        Text("2")
    }
}

struct InvoicesDetail : View  {
    var body: some View {
        Text("3")
    }
}

struct HomeMenuRow : View  {
    var itemText: String
    var body: some View {
        Text(itemText)
    }
}

struct ContentView: View {

    enum MenuItem: String, CaseIterable, Identifiable {
        var id : MenuItem {
            self
        }

        case firstCase = "Staff"
        case secondCase = "Projects"
        case thirdCase = "Invoices"
    }

    func getDestination(itemText: String) -> AnyView {

        let value = MenuItem(rawValue: itemText)

        switch value {

        case .some(.firstCase):
            return AnyView(InvoicesDetail())
        case.some(.secondCase):
            return AnyView(ProjectsDetail())
        case .none:
            return AnyView(Text("a"))
        case .some(.thirdCase):
            return AnyView(StaffDetail())
        }
    }

    var body: some View {
        NavigationView {
            List(MenuItem.allCases) { itemText in

                NavigationLink(destination: self.getDestination(itemText: itemText.rawValue)) {
                    HomeMenuRow(itemText: itemText.rawValue)
                }

            }.navigationBarTitle(Text("Menu"))

        }
    }
}

【讨论】:

    【解决方案2】:

    我可以使用if-else 语句使其工作:

            NavigationView {
                List(MenuItem.allCases) { itemText in
                    if itemText == MenuItem.firstCase {
                        NavigationLink(destination: Text("first")) {
                            Text(itemText.rawValue)
                        }
                    } else if itemText == MenuItem.secondCase {
                        NavigationLink(destination: Text("bar")) {
                            Text(itemText.rawValue)
                        }
                    } else {
                        NavigationLink(destination: Text("baz")) {
                            Text(itemText.rawValue)
                        }
                    }
                }
                .navigationBarTitle(Text("Menu"))
            }
    

    我明确添加了MenuItem 以使编译器满意。 显然,函数构建器中的if-else 子句无法处理 complex 类型推断。

    【讨论】:

      【解决方案3】:

      当菜单有部分时,方法有点不同:

      import SwiftUI
      
      struct MenuView: View {
          enum MenuItem: String {
              case staff = "Staff"
              case projects = "Projects"
              case invoices = "Invoices"
              case about = "About"
              case feedback = "Fourth"
      
              static let infoSection: [MenuItem] = [.staff, .projects, .invoices]
              static let helpSection: [MenuItem] = [.about, .feedback]
          }
      
          var body: some View {
              NavigationView {
                  List {
                      makeSection(title: "Info", items: MenuItem.infoSection)
                      makeSection(title: "Help", items: MenuItem.helpSection)
                  }
                  .navigationBarTitle("Menu")
              }
          }
      
          private func makeSection(title: String, items: [MenuItem]) -> some View {
              Section(header: Text(title)) {
                  ForEach(items, id: \.self) { item in
                      NavigationLink(destination: self.destination(forItem: item)) {
                          Text(item.rawValue)
                      }
                  }
              }
          }
      
          private func destination(forItem item: MenuItem) -> some View {
              switch item {
                  case .staff: return AnyView(Text("Staff View"))
                  case .projects: return AnyView(Text("Projects View"))
                  case .invoices: return AnyView(Text("Invoices View"))
                  case .about: return AnyView(Text("About View"))
                  case .feedback: return AnyView(Text("Feedback View"))
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-04-06
        • 2020-06-03
        • 2021-08-09
        • 1970-01-01
        • 2021-08-16
        • 2020-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多