SwiftUI 单击列表中的一行,将该列表中的每一行设置为 true

SwiftUI Clicking on one Row in a List, sets every row on that list to true

我有一个看起来像这样的列表:

但是当我点击一行时,每一行中的每个圆圈都会得到 activated/deactivated。我现在在这个问题上坐了几个小时,不知道该怎么做。谁能帮帮我?

我认为问题与 DispatchQueue.main.async 行有关。但是如果我在代码中不使用DispatchQueue.main.async,列表是空的,无法填充。如果我不这样做 DispatchQueue.main.async,我会收到两次以下错误:

Modifying state during view update, this will cause undefined behavior.

所以如果我使用 DispatchQueue.main.async 列表可以被填充并且不是空的。但正如我之前所述,新问题是,当我单击一行时,列表中的每个圆(来自所有行)都会得到 activated/deactivated.

这是我的代码:

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")

        }
    
    
}

整个列表只有一个 isChecked。每一行都使用相同的变量,因此当其中一个被点击时,所有的变量都会改变。

根据代码,列表中的每一项似乎都有一个 isDone 成员。尝试将图像名称的 self.isChecked 替换为 a.isDone。然后尝试将按钮操作从 self.toggle 更改为 { a.isDone.toggle() }

所以您的列表如下所示。

List(listItems) { a in
    Button(action: { 
        a.isDone.toggle()
    }){
        HStack {
            Image(systemName: a.isDone ? "checkmark.circle.fill" : "circle")
            Text(a.text)
        }
    }
}.offset(y: -50)