通过 NavigationLink - SwiftUI 对不同数据使用相同的视图
Using same View for different data via NavigationLink - SwiftUI
为了尽可能少地重现代码,我创建了一个 OwnListView
,它得到一个 title
、subtitle
、List
个对象,我可以从中选择一个Continue button
,但现在我有一个问题,即如何最好地使用 NavigationLinks 更改视图以获得具有不同数据的相同视图。
因为我想使用视图不只是2次,而是更频繁...
现在开始执行:
我想首先显示带有“最佳男性名字”的视图,然后是带有“最佳女性名字”的相同视图,然后是带有“最佳颜色”的相同视图,依此类推。
我没有找到完全适合我的问题 - 我希望有人能帮助我
这是我的 StartView
,这是第一个视图,我的 ListModel 已初始化
struct StartView: View {
@StateObject var listModel = ListModel()
var body: some View {
NavigationView{
NavigationLink(destination: {
OwnListView(listModel: listModel,
title: "MaleNames",
items: ["Todd", "Liam", "Noah", "Oliver", "James", "William"],
choosedItems: $listModel.maleNames)
}, label: {
Text("Start")
.bold()
})
}
}
}
然后是我的ListView
,我想从中得到几个,这样我就可以做一个“调查”或类似的事情:
struct OwnListView: View {
//ListModel
@ObservedObject var listModel: ListModel
var title: String
var items: [String]
@Binding var choosedItems: [String]
var body: some View {
VStack{
Text(title)
.font(.largeTitle)
.bold()
ForEach(items, id: \.self){ item in
let alreadyInList: Bool = choosedItems.contains(where: { [=11=] == item })
Button(action: {
if alreadyInList {
choosedItems.removeAll(where: { [=11=] == item })
} else {
choosedItems.append(item)
}
}, label: {
//Can be an own View, but for simplicity
ZStack{
Rectangle()
.fill(alreadyInList ? .black : .purple)
.frame(width: 250, height: 50)
Text(item)
.bold()
.foregroundColor(.white)
}
})
}
Spacer()
//After Best Male Names - female names
NavigationLink(destination: {
OwnListView(listModel: listModel,
title: "Best Female Names",
items: ["Jessica", "Monica", "Stephanie"],
choosedItems: $listModel.femaleNames)
}, label: {
Text("Continue")
})
/*
//After Best Female Names - colors
NavigationLink(destination: {
OwnListView(listModel: listModel,
title: "Best Colors",
items: ["Pink", "Blue", "Yellow", "Green"],
choosedItems: listModel.colors)
}, label: {
Text("Continue")
})
*/
Spacer()
}.navigationBarTitleDisplayMode(.inline)
}
}
只有一个视图可以重新加载的一种方法是动态定义其内容。可以使用枚举来保存调查的状态:
class ListModel: ObservableObject {
// The enum is the list of tests
enum Choosing {
case male
case female
case color
// Define each test title
var title: String {
switch self {
case .male:
return "Male Names"
case .female:
return "Female Names"
case .color:
return "Color Names"
}
}
// define each test possible values
var items: [String] {
switch self {
case .male:
return ["Todd", "Liam", "Noah", "Oliver", "James", "William"]
case .female:
return ["Jessica", "Monica", "Stephanie"]
case .color:
return ["Pink", "Blue", "Yellow", "Green"]
}
}
// choosing next test
var next: Choosing? {
switch self {
case .male:
return .female
case .female:
return .color
case .color:
return nil
}
}
}
@Published var choosedItems: [Choosing:[String]] = [.male:[], .female:[], .color:[]]
}
struct StartView: View {
@StateObject var listModel = ListModel()
var body: some View {
NavigationView{
NavigationLink(destination: {
// Just give model and first test
OwnListView(listModel: listModel,
choosing: .male)
}, label: {
Text("Start")
.bold()
})
}
}
}
普遍看法:
struct OwnListView: View {
//ListModel
@ObservedObject var listModel: ListModel
var choosing: ListModel.Choosing
// Use enum var to get title and items
var title: String {
choosing.title
}
var items: [String] {
choosing.items
}
var body: some View {
VStack{
Text(title)
.font(.largeTitle)
.bold()
ForEach(choosing.items, id: \.self){ item in
// Use the current test result
let alreadyInList: Bool = listModel.choosedItems[choosing]?.contains(where: { [=11=] == item }) ?? false
Button(action: {
if alreadyInList {
listModel.choosedItems[choosing]?.removeAll(where: { [=11=] == item })
} else {
listModel.choosedItems[choosing]?.append(item)
}
}, label: {
//Can be an own View, but for simplicity
ZStack{
Rectangle()
.fill(alreadyInList ? .black : .purple)
.frame(width: 250, height: 50)
Text(item)
.bold()
.foregroundColor(.white)
}
})
}
Spacer()
// if still somthing test next
if let next = choosing.next {
NavigationLink(destination: {
OwnListView(listModel: listModel,
choosing: next)
}, label: {
Text("Continue")
})
} else {
// Here you can have a button to navigation link to go to end of survey
Text("Finish")
}
Spacer()
}.navigationBarTitleDisplayMode(.inline)
}
}
注意:枚举、标题和值可以来自外部 json 文件以使其更通用。这只是一种方法。
要完成调查,只需完成枚举定义。
为了尽可能少地重现代码,我创建了一个 OwnListView
,它得到一个 title
、subtitle
、List
个对象,我可以从中选择一个Continue button
,但现在我有一个问题,即如何最好地使用 NavigationLinks 更改视图以获得具有不同数据的相同视图。
因为我想使用视图不只是2次,而是更频繁...
现在开始执行: 我想首先显示带有“最佳男性名字”的视图,然后是带有“最佳女性名字”的相同视图,然后是带有“最佳颜色”的相同视图,依此类推。
我没有找到完全适合我的问题 - 我希望有人能帮助我
这是我的 StartView
,这是第一个视图,我的 ListModel 已初始化
struct StartView: View {
@StateObject var listModel = ListModel()
var body: some View {
NavigationView{
NavigationLink(destination: {
OwnListView(listModel: listModel,
title: "MaleNames",
items: ["Todd", "Liam", "Noah", "Oliver", "James", "William"],
choosedItems: $listModel.maleNames)
}, label: {
Text("Start")
.bold()
})
}
}
}
然后是我的ListView
,我想从中得到几个,这样我就可以做一个“调查”或类似的事情:
struct OwnListView: View {
//ListModel
@ObservedObject var listModel: ListModel
var title: String
var items: [String]
@Binding var choosedItems: [String]
var body: some View {
VStack{
Text(title)
.font(.largeTitle)
.bold()
ForEach(items, id: \.self){ item in
let alreadyInList: Bool = choosedItems.contains(where: { [=11=] == item })
Button(action: {
if alreadyInList {
choosedItems.removeAll(where: { [=11=] == item })
} else {
choosedItems.append(item)
}
}, label: {
//Can be an own View, but for simplicity
ZStack{
Rectangle()
.fill(alreadyInList ? .black : .purple)
.frame(width: 250, height: 50)
Text(item)
.bold()
.foregroundColor(.white)
}
})
}
Spacer()
//After Best Male Names - female names
NavigationLink(destination: {
OwnListView(listModel: listModel,
title: "Best Female Names",
items: ["Jessica", "Monica", "Stephanie"],
choosedItems: $listModel.femaleNames)
}, label: {
Text("Continue")
})
/*
//After Best Female Names - colors
NavigationLink(destination: {
OwnListView(listModel: listModel,
title: "Best Colors",
items: ["Pink", "Blue", "Yellow", "Green"],
choosedItems: listModel.colors)
}, label: {
Text("Continue")
})
*/
Spacer()
}.navigationBarTitleDisplayMode(.inline)
}
}
只有一个视图可以重新加载的一种方法是动态定义其内容。可以使用枚举来保存调查的状态:
class ListModel: ObservableObject {
// The enum is the list of tests
enum Choosing {
case male
case female
case color
// Define each test title
var title: String {
switch self {
case .male:
return "Male Names"
case .female:
return "Female Names"
case .color:
return "Color Names"
}
}
// define each test possible values
var items: [String] {
switch self {
case .male:
return ["Todd", "Liam", "Noah", "Oliver", "James", "William"]
case .female:
return ["Jessica", "Monica", "Stephanie"]
case .color:
return ["Pink", "Blue", "Yellow", "Green"]
}
}
// choosing next test
var next: Choosing? {
switch self {
case .male:
return .female
case .female:
return .color
case .color:
return nil
}
}
}
@Published var choosedItems: [Choosing:[String]] = [.male:[], .female:[], .color:[]]
}
struct StartView: View {
@StateObject var listModel = ListModel()
var body: some View {
NavigationView{
NavigationLink(destination: {
// Just give model and first test
OwnListView(listModel: listModel,
choosing: .male)
}, label: {
Text("Start")
.bold()
})
}
}
}
普遍看法:
struct OwnListView: View {
//ListModel
@ObservedObject var listModel: ListModel
var choosing: ListModel.Choosing
// Use enum var to get title and items
var title: String {
choosing.title
}
var items: [String] {
choosing.items
}
var body: some View {
VStack{
Text(title)
.font(.largeTitle)
.bold()
ForEach(choosing.items, id: \.self){ item in
// Use the current test result
let alreadyInList: Bool = listModel.choosedItems[choosing]?.contains(where: { [=11=] == item }) ?? false
Button(action: {
if alreadyInList {
listModel.choosedItems[choosing]?.removeAll(where: { [=11=] == item })
} else {
listModel.choosedItems[choosing]?.append(item)
}
}, label: {
//Can be an own View, but for simplicity
ZStack{
Rectangle()
.fill(alreadyInList ? .black : .purple)
.frame(width: 250, height: 50)
Text(item)
.bold()
.foregroundColor(.white)
}
})
}
Spacer()
// if still somthing test next
if let next = choosing.next {
NavigationLink(destination: {
OwnListView(listModel: listModel,
choosing: next)
}, label: {
Text("Continue")
})
} else {
// Here you can have a button to navigation link to go to end of survey
Text("Finish")
}
Spacer()
}.navigationBarTitleDisplayMode(.inline)
}
}
注意:枚举、标题和值可以来自外部 json 文件以使其更通用。这只是一种方法。 要完成调查,只需完成枚举定义。