SwiftUI При нажатии на одну строку в списке для каждой строки в этом списке устанавливается значение true. - PullRequest
0 голосов
/ 05 августа 2020

У меня есть список, который выглядит так:

введите описание изображения здесь

Но когда я нажимаю на одну строку, каждый кружок в каждой строке активируется / деактивируется. Я сижу над этой проблемой уже несколько часов и не знаю, что делать. Кто-нибудь может мне помочь?

Думаю, проблема связана со строкой DispatchQueue.main.async. Но если я не использую DispatchQueue.main.async в коде, список будет пуст и не может быть заполнен. И если я не сделаю DispatchQueue.main.async, я дважды получу следующую ошибку:

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

Итак, если я использую DispatchQueue.main.async, список может быть заполнен и не будет пустым. Но, как я описывал ранее, новая проблема заключается в том, что когда я щелкаю строку, каждый круг (из всех строк) в списке активируется / деактивируется.

Это мой код:

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 Ответ

1 голос
/ 05 августа 2020

На весь список только один 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)
...