Home > OS >  How to access property in viewmodel to view in SwiftUI?
How to access property in viewmodel to view in SwiftUI?

Time:03-19

I have viewmodel and view i have return some API logic in viewmodel and getting one dictionary after some logic..i want to access that dictionary value from view for ex.

viewmodel.someDic

but for now every-time i am getting empty dic.

class Viewmodel: ObservableObject {
@Published private var poductDetails:[String:ProductDetail] = [:]

   func createItems(data: ProductRootClass) {
        var productDetils = [String: SelectedProductDetail](){
         //some logic
         productDetils // with some object
         self.poductDetails = productDetils
        }
    }
}


struct View: View {
    @StateObject var viewModel: ViewModel

  var body: some View {
        VStack(alignment: .leading) {
           Text("\(viewModel.poductDetails)")
        }
        .onAppear(perform: {
            print("\(viewModel.poductDetails)")
        })
   }
}

I want to access this dictionary from view.

I tried accessing by returning productDetils from any function but get empty everytime.

may i know the way to access property from viewmodel to view?

CodePudding user response:

You need a class conforming to ObservableObject and a property marked as @Published

class ViewModel : ObservableObject {

   @Published var productDetails = [String:ProductDetail]()

   func createItems(data: ProductRootClass) {
        var productDetils = [String: SelectedProductDetail]()
         //some logic
         productDetils // with some object
         self.productDetails = productDetils
        
    }
}

Whenever the property is modified the view will be updated.

In the view create an instance and declare it as @StateObject

struct ContentView: View {
  @StateObject var viewModel = ViewModel()

  var body: some View {
        VStack(alignment: .leading) {
           ForEach(viewModel.productDetails.keys.sorted(), id: \.self) { key in
               Text("\(viewModel.poductDetails[key]["someOtherKey"] as! String)")
           }
        }
   }
}

I would prefer an array as model, it's easier to access

CodePudding user response:

You need to get rid of the view model and make a proper model.

class Model: ObservableObject {
    @Published private var productDetails:[ProductDetail] = []

}

struct ProductDetail: Identifiable {
    let id = UUID()
    var title: String

}

Now you can do ForEach(model.productDetails)

CodePudding user response:

You can make your viewModel as a Singleton.

class ViewModel : ObservableObject {
    static let viewModelSingleton = ViewModel()
    @Published var productDetails = [String : ProductDetail]()
    \\API logic}

Access this viewModel Singleton in the view

struct view : View {
    @ObservedObject var viewModelObject = ViewModel.viewModelSingleton

    var body: some View {
         VStack(alignment: .leading) {
             Text("\(viewModelObject.productDetails)")
      }
 }}
  • Related