SwiftUI从列表导航到其他视图

时间:2020-04-13 13:09:23

标签: swift swiftui swift5

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

enter image description here

我想要做的是将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对象中使用它。

3 个答案:

答案 0 :(得分:3)

尝试一下:

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

        }
    }
}

答案 1 :(得分:1)

我可以使用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 类型推断。

答案 2 :(得分:0)

菜单包含部分时的方法略有不同:

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