SwiftUI - 更改 ForEach 中的结构数据集?



我是编程和SwiftUI的新手,我正在制作这个应用程序,用户可以在其中选择这些标记为A-D的按钮。他们可能会选择超过 1 个,我希望当他们单击按钮时,背景颜色将从灰色变为绿色。但是,如果我将底部代码中的"//Here"替换为

Data.Selected = true
Data.Colour = .green

我收到一条错误消息,指出"无法分配给属性:"数据"是"让"常量"。我明白这意味着什么,但我不知道如何将数据更改为 var。我尝试在"Data in"前面键入var,但出现此错误,而不是"一行上的连续语句必须用';'分隔。".无论如何我可以直接修改数据/按钮数据吗?或者有解决方法吗?

struct Buttons: Hashable {
var Crit: String
var Selected: Bool
var Colour: Color
}
var ButtonsData = [
Buttons(Crit: "A", Selected: false, Colour: Color(.systemGray4)),
Buttons(Crit: "B", Selected: false, Colour: Color(.systemGray4)),
Buttons(Crit: "C", Selected: false, Colour: Color(.systemGray4)),
Buttons(Crit: "D", Selected: false, Colour: Color(.systemGray4))
]
struct CritView: View {

@Binding var CritBoard: Bool
@Binding var BackgroundColor: Color

var body: some View {
ZStack(alignment: .topLeading) {

ScrollView(.vertical, showsIndicators: false) {
HStack(spacing: 15) {
ForEach(ButtonsData, id: .self) { Data in
Button(action: {
// HERE
}) {
Text(Data.Crit)
.font(.system(size: 30))
}
.frame(width: 65, height: 55)
.background(Data.Colour)
.cornerRadius(10)
}
}
.padding(.top, 50)
}
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height/8)
.padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom)
.background(Color(.white))
.cornerRadius(25)

Button(action: {
self.CritBoard.toggle()
self.BackgroundColor = .white
}) {
Image(systemName: "xmark").foregroundColor(.black)
}.padding(25)
}
}
}

这是可能的解决方案 - 创建索引/值元组数组并按索引修改原始容器中的数据:

ForEach(Array(ButtonsData.enumerated()), id: .element) { i, Data in
Button(action: {
ButtonsData[i].Selected = true
ButtonsData[i].Colour = .green
}) {
Text(Data.Crit)
.font(.system(size: 30))
}
.frame(width: 65, height: 55)
.background(Data.Colour)
.cornerRadius(10)
}

好吧,我认为很多人实际上不会遇到相同/类似的问题,但这是我的工作代码。该代码既使用了@Aspersi的答案,也使用了 Hacking with Swift 文章中的代码。(它可能不是最简化的代码,但它至少现在有效(

ForEach(Array(ButtonsData.enumerated()), id: .element) { i, Data in
Button(action: {
self.AllData[i].Selected.toggle()
if self.AllData[i].Selected == true {
self.AllData[i].Colour = .green
} else {
self.AllData[i].Colour = Color(.systemGray4)
}
}) {
Text(Data.Crit)
.font(.system(size: 30))
}
.frame(width: 65, height: 55)
.background(self.AllData[i].Colour)
.cornerRadius(10)
}

完整代码如下

struct Buttons: Hashable {
var Crit: String
var Selected: Bool = false
var Colour: Color
}
var ButtonsData = [
Buttons(Crit: "A", Selected: false, Colour: Color(.systemGray4)),
Buttons(Crit: "B", Selected: false, Colour: Color(.systemGray4)),
Buttons(Crit: "C", Selected: false, Colour: Color(.systemGray4)),
Buttons(Crit: "D", Selected: false, Colour: Color(.systemGray4))
]
struct CritView: View {

@Binding var CritBoard: Bool
@Binding var BackgroundColor: Color

@State private var AllData = ButtonsData

var body: some View {
ZStack(alignment: .topLeading) {

ScrollView(.vertical, showsIndicators: false) {
HStack(spacing: 15) {
ForEach(Array(ButtonsData.enumerated()), id: .element) { I, Data in
Button(action: {
self.AllData[i].Selected.toggle()
if self.AllData[i].Selected == true {
self.AllData[i].Colour = .green
} else {
self.AllData[i].Colour = Color(.systemGray4)
}
}) {
Text(Data.Crit)
.font(.system(size: 30))
}
.frame(width: 65, height: 55)
.background(self.AllData[i].Colour)
.cornerRadius(10)
}
}
.padding(.top, 50)
}
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height/8)
.padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom)
.background(Color(.white))
.cornerRadius(25)

Button(action: {
self.CritBoard.toggle()
self.BackgroundColor = .white
}) {
Image(systemName: "xmark").foregroundColor(.black)
}.padding(25)
}
}
}

最新更新