SwiftUI单击列表中的一行,将该列表中的每一行设置为true
Posted
技术标签:
【中文标题】SwiftUI单击列表中的一行,将该列表中的每一行设置为true【英文标题】:SwiftUI Clicking on one Row in a List, sets every row on that list to true 【发布时间】:2020-08-05 20:05:16 【问题描述】:我有一个看起来像这样的列表:
但是当我点击一行时,每一行中的每个圆圈都会被激活/停用。我现在在这个问题上坐了几个小时,不知道该怎么办。谁能帮帮我?
我认为问题与DispatchQueue.main.async
线有关。但是如果我在代码中不使用DispatchQueue.main.async
,则列表为空,无法填充。如果我不这样做DispatchQueue.main.async
,我会两次收到以下错误:
Modifying state during view update, this will cause undefined behavior.
所以如果我使用DispatchQueue.main.async
,列表可以被填充并且不为空。但正如我之前所描述的,新问题是,当我单击一行时,列表中的每个 Circle(来自所有行)都会被激活/停用。
这是我的代码:
struct zettelDetailView: View
var info: CreateInfo
@State var isChecked: Bool = false
func toggle()
isChecked = !isChecked
@State var listItems = [CreateZettelDetailViewText]()
@State var executeThisAsyncThing: Bool = true
private func changeInfoListToArray()
//String ist folgendermaßen aufgebaut:
//"Text/-t;" t = true; f = false "/-" und ";" sind splitter
// var returnArray = [CreateZettelDetailViewText]()
// let infoStr = info.list
let infoStr = "Das-t;Ist-f;Ein-f;Test-t;"
let infoArr1 = infoStr.split(separator: ";")
var infoArr2 = [[String]]()
print(infoArr1.count)
if infoArr1.count != 0
for i in 0...(infoArr1.count - 1)
let x = infoArr1[i]
let y = x.split(separator: "-")[0] //text
let z = x.split(separator: "-")[1] //bool
var arr2 = [String]()
arr2.append(String(y))
arr2.append(String(z))
var zBool: Bool = false
if z == "t"
zBool = true
else if z == "f"
zBool = false
infoArr2.append(arr2)
self.listItems.append(CreateZettelDetailViewText(text: "\(String(y))", isDone: zBool))
executeThisAsyncThing = false
var body: some View
// listItems = changeInfoListToArray()
DispatchQueue.main.async
if self.executeThisAsyncThing
self.changeInfoListToArray()
return VStack
VStack
Text(info.name)
.font(.largeTitle)
Text("\(info.day) - \(info.time)")
.offset(y: -50)
List(listItems) a in
Button(action: self.toggle
//
//
// if a.isDone
// self.isChecked = true
// else if !a.isDone
// self.isChecked = false
//
//
// print()
// print(a.id)
// print(a.text)
// print(a.isDone)
// print()
//
//
)
HStack
Image(systemName: self.isChecked ? "checkmark.circle.fill" : "circle")
Text(a.text)
.onAppear()
self.isChecked = true
.offset(y: -50)
Button(action: addRow)
Image(systemName: "plus.app.fill")
.offset(y: -20)
.font(.largeTitle)
private func addRow()
// var arr = [[String]]()
// arr = getZettelData()
// arr.append(["ZettelName", "\(time)", "\(day)"])
//
// let defaults = UserDefaults.standard
// defaults.set(arr, forKey: "SavedZettelArray")
【问题讨论】:
【参考方案1】:整个列表只有一个isChecked
。每一行都使用相同的变量,因此当其中一个被点击时,它们都会改变。
根据代码,列表中的每个项目都有一个isDone
成员。尝试将 self.isChecked
替换为 a.isDone
作为图像名称。然后尝试将按钮操作从self.toggle
更改为 a.isDone.toggle()
所以你的 List 如下所示。
List(listItems) a in
Button(action:
a.isDone.toggle()
)
HStack
Image(systemName: a.isDone ? "checkmark.circle.fill" : "circle")
Text(a.text)
.offset(y: -50)
【讨论】:
这可以作为评论发布。在您的答案中添加解决 OP 问题的方法。 我同意。但是,我没有足够的代表发表评论。我会在回复中添加更多内容以使其成为解决方案。 在 SwiftUI 测试版中有一个名为Label
的新组件,它具有图像和文本。基本上可以用来代替HStack
。确实取决于所使用的 SwiftUI 版本 :)
我尝试了你的解决方案,但它对我不起作用,因为Cannot assign to property: 'a' is a 'let' constant
你知道如何切换我的a
吗?以上是关于SwiftUI单击列表中的一行,将该列表中的每一行设置为true的主要内容,如果未能解决你的问题,请参考以下文章