Reputation: 568
I have a List that looks like that:
But when I click on one row, every circle in every row gets activated/deactivated. I am sitting on that problem for a few Hours now and don't know what to do. Can anyone help me?
I think the problem has something to do with the DispatchQueue.main.async
Line. But if I don't use DispatchQueue.main.async
in the code, the list is empty and cannot be filled. And if I wouldn't do DispatchQueue.main.async
, I get the following Error twice:
Modifying state during view update, this will cause undefined behavior.
So if I use DispatchQueue.main.async
the list can be filled and is not empty. But as I described earlier, the new Problem is, that when I click a Row, every Circle(from all rows) in the list gets activated/deactivated.
This is my code:
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")
}
}
Upvotes: 0
Views: 1506
Reputation: 490
There's only one isChecked
for the entire list. Each row is using the same variable and so when one of them is tapped, all of them change.
Based on the code it looks like each item in the list has an isDone
member. Try replacing self.isChecked
with a.isDone
for the Image name. Then try changing the button action from self.toggle
to { a.isDone.toggle() }
So you're List would look like the following.
List(listItems) { a in
Button(action: {
a.isDone.toggle()
}){
HStack {
Image(systemName: a.isDone ? "checkmark.circle.fill" : "circle")
Text(a.text)
}
}
}.offset(y: -50)
Upvotes: 3