2

So I know my items are being added to the 'vitallist'(through printing the list in the terminal), but I am not seeing them appear on list view. I think it has something to do with the 'ObservedObject' not being linked correctly. Any suggestions?

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 Answers3

3

I also had same problem. I am not sure why, but it works that creating a new element in the array, not changing the element itself. I confirmed directly updating works only in data, but not for binding UI.

In my code, element change in TobuyData class.


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
        }

    }
}

In View

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) }
...

p.s.

Changing Tobuy Class to Struct made direct element updating work, the comment out part above. This referenced to Apple's official tutorial: "Handling User Input"

0

change

@ObservedObject var vitallist = VitalList()

to

@EnvironmentObject var vitallist = VitalList()
Ernist Isabekov
  • 1,205
  • 13
  • 20
0

The code seems fine. I added a simple add method to VitalList

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

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

And a Button to the body

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

The list updates as expected. check your code that adds your items to

 @Published var vitallist = [Vital]()

Are you using the same instance of VitalList? A singleton might help. https://developer.apple.com/documentation/swift/cocoa_design_patterns/managing_a_shared_resource_using_a_singleton

lorem ipsum
  • 21,175
  • 5
  • 24
  • 48