SwiftUI - 更改 ForEach 中的结构数据集?
Posted
技术标签:
【中文标题】SwiftUI - 更改 ForEach 中的结构数据集?【英文标题】:SwiftUI - Changing struct data set in ForEach? 【发布时间】:2020-06-23 14:12:39 【问题描述】:我是编程和 SwiftUI 的新手,我正在制作这个应用程序,用户可以在其中选择标记为 A-D 的这些按钮。他们可能会选择超过 1 个,我希望当他们点击按钮时,背景颜色会从灰色变为绿色。但是,如果我将底部代码中的“// Here”替换为
Data.Selected = true
Data.Colour = .green
我收到一条错误消息,提示“无法分配给属性:'Data' 是 'let' 常量”。我明白这意味着什么,但我不知道如何将 Data 更改为 var。我尝试在“数据输入”前键入 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)
【问题讨论】:
【参考方案1】:这是可能的解决方案 - 创建索引/值元组数组并通过索引修改原始容器中的数据:
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)
【讨论】:
感谢您的回答!复制并粘贴您的代码后,没有任何错误,但不幸的是没有工作。问题是,虽然“ButtonsData[i].Colour”确实发生了变化,但“.background(ButtonsData[I].Colour)”却没有,因为它不是@State 变量。我做了一些搜索,发现这篇 Hacking with Swift 文章很有帮助 (hackingwithswift.com/books/ios-swiftui/…)。因此,我添加了“@State private var AllData = ButtonsData”并将“ButtonsData[I].Colour”更改为“self.AllData[i].Colour”。【参考方案2】:好吧,我不认为很多人实际上会遇到相同/相似的问题,但这是我的工作代码。该代码同时使用了@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)
【讨论】:
以上是关于SwiftUI - 更改 ForEach 中的结构数据集?的主要内容,如果未能解决你的问题,请参考以下文章
使用 ForEach SwiftUI Core Data 仅更改列表中的一项
SwiftUI:使用 Picker(分段)更改 ForEach 源或获取请求