Home > Mobile >  @Published array value not updating in swiftUIView
@Published array value not updating in swiftUIView

Time:10-07

**ViewModel**

class ViewModel : ObservableObject{
         @Published var options = [Item]()
         @Published var cartArray = [Order]()



      func addCart ( ){
            cartArray.append(Order(id: 1, name: "Oil", options:self.options))

  }


}


 

 **Model** 

struct Order: Codable {
  var  id: Int
  var name: String
  var options : [Item] =  [Item]()
}



struct Item: Codable{
    var name: String
    var id: Int
    var price: Double
  
}


**Printing of self.options** 

[AppName.Item(name: "Groundnut oil", id: 10, price: 10.0)], 
[AppName.Item(name: "Coconut oil", id: 11, price: 18.0)]


**View**


struct CreateOrderView: View {
 @ObservedObject var vwModel = ViewModel()
   var body: some View {
            
            ListView()
    
            Button(action: {
                print(vwModel.options) //prints as [](i.e no elements)
                vwModel.addCart()
                

            }, label: {
                Text("Add")
           
                .frame(maxWidth: .infinity, minHeight: 60)
                .background(Color.red)
                

            })

}

}
struct ListView: View{

@StateObject var vwModel = ViewModel()
 var body: some View {
   List(vwModel.OptionsList) {row in
       //Display Items
        print(vwModel.options) // Here it prints options(elements in array)

}
 
}
}

@Published array of viewModel is being updated in ListView , but not updated in CreateOrderView.

Any suggestions would be helpful

CodePudding user response:

Here is the issue: @ObservedObject var vwModel = ViewModel()

When you creat an @ObservedObject, should should always inject the value, not create it on the spot. Because everything your view refreshes now. It will create a new ViewModel(), hence you wont have any new values inside the ViewModel.

Think of it like this:

  • States and StateObjects is locally created
  • ObservedObjects and Bindings are injected

CodePudding user response:

I fixed my code with this and its working now.

I used dependency injection and called ListView like this

struct CreateOrderView: View {

  @ObservedObject var vwModel = ViewModel()
    
     var body: some View {
           ListView(vwModel: vwModel). // Fix to my non-working code
            Button(action: {
            print(vwModel.options) // Now it prints the options here too
            vwModel.addCart()
            

        }, label: {
            Text("Add")
       
            .frame(maxWidth: .infinity, minHeight: 60)
            .background(Color.red)
            

        })
}
}

struct ListView: View{

  @ObservedObject var vwModel = ViewModel()
      
     var body: some View {
        List(vwModel.OptionsList) {row in
        //Display Items
        print(vwModel.options) // Here it prints options(elements in array)

}
}
}
  • Related