SwiftUI 从 List 导航到不同的视图

SwiftUI navigate to different view from List

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

我想做的是将 NavigationLink 与不同的目的地视图一起使用。我尝试在列表块中使用 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"))
        }
    }
}

看起来找到了一些解决方案 但不确定如何在 List 对象中使用它。

试试这个:

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"))

        }
    }
}

我可以使用 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 子句无法处理 复杂的 类型推断。

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

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"))
        }
    }
}