skip to Main Content

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?

3

Answers


  1. 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

    Login or Signup to reply.
  2. 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)")
          }
     }}
    
    Login or Signup to reply.
  3. 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)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search