我有一个使用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
对象中使用它。
答案 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"))
}
}
}