Как мне сделать Observable Object обновить список? - PullRequest
1 голос
/ 26 января 2020

Итак, я знаю, что мои товары добавляются в «виталлист» (через печать списка в терминале), но я не вижу их в списке. Я думаю, что это как-то связано с тем, что ObservedObject некорректно связан. Какие-либо предложения?

struct Vital: Identifiable {
    let id = UUID()
    var name: String

}

class VitalList:ObservableObject {
   @Published var vitallist = [Vital]()
}

struct Row: View {
    var vital: Vital

    @State var completed:Bool = false
    var body: some View {
        HStack{
            Image(systemName: completed ? "checkmark.circle.fill" : "circle").onTapGesture {
                self.completed.toggle()
            }
            Text(vital.name)
        }
    }
}
struct Lists: View {

    @ObservedObject var vitallist = VitalList()

    var body: some View {
        NavigationView{
            List{
                Section(header: Text("Vital")){
                    ForEach(vitallist.vitallist){ item in
                        Row(vital: item)
                    }
                }
              }
            }
          }
        }

Ответы [ 3 ]

1 голос
/ 23 марта 2020

У меня тоже была такая же проблема. Я не уверен, почему, но это работает, что создание нового элемента в массиве, а не изменение самого элемента. Я подтвердил, что прямое обновление работает только в данных, но не для привязки пользовательского интерфейса.

В моем коде изменение элемента в TobuyData классе.


class Tobuy: Identifiable {
    let id = UUID()
    var thing: String
    var isDone = false

    init(_ thing: String, isDone: Bool = false) {
        self.thing = thing
        self.isDone = isDone
    }
}

class TobuyData: ObservableObject {
    @Published var tobuys: [Tobuy]

    init() {
        self.tobuys = [
            Tobuy("banana"),
            Tobuy("bread"),
            Tobuy("pencil"),
        ]
    }

    func toggleDone(_ tobuy: Tobuy) {
        if let j = self.tobuys.firstIndex(where: { $0.id == tobuy.id }) {
            self.tobuys[j] = Tobuy(self.tobuys[j].thing, isDone: !self.tobuys[j].isDone)
//          self.tobuys[j].isDone.toggle() // this works only in data, but not for binding UI
        }

    }
}

В представлении

struct ContentView: View {
    @EnvironmentObject var tobuyData: TobuyData

    var body: some View {

            List {
                ForEach(tobuyData.tobuys) { tobuy in

                        Text(tobuy.thing)
                            .strikethrough(tobuy.isDone)
                            .onTapGesture { self.tobuyData.toggleDone(tobuy) }
...

ps

Изменение Tobuy Class на Struct сделало прямое обновление элемента работающим, часть комментария выше. Это ссылка на официальный учебник Apple: «Обработка пользовательского ввода»

0 голосов
/ 28 января 2020

Код кажется нормальным. Я добавил простой метод добавления в VitalList

class VitalList:ObservableObject {
     @Published var vitallist = [Vital]()

     func addVital(){
         self.vitallist.append(Vital(name: UUID().description))
     }
}

и кнопку в теле

var body: some View {
    NavigationView{
        VStack{
            Button(action: {self.vitallist.addVital()}, label: {Text("add-vital")})
            List{
                Section(header: Text("Vital")){
                    ForEach(vitallist.vitallist){ item in
                        Row(vital: item)
                    }
                }
            }
        }
    }
}

Список обновляется, как и ожидалось. проверьте код, который добавляет ваши элементы в

 @Published var vitallist = [Vital]()

Используете ли вы тот же экземпляр VitalList? Синглтон может помочь. https://developer.apple.com/documentation/swift/cocoa_design_patterns/managing_a_shared_resource_using_a_singleton

0 голосов
/ 28 января 2020

изменить

@ObservedObject var vitallist = VitalList()

на

@EnvironmentObject var vitallist = VitalList()
...