Home > Mobile >  How do I pass a value to a ViewModel from a View using the .environmentObject() in Swift?
How do I pass a value to a ViewModel from a View using the .environmentObject() in Swift?

Time:01-12

I have created a ViewModel with an init() that accepts a parameter something like this. PS: Learning swift and swiftUI

//UsersViewModel.swift
class UsersViewModel: ObservableObject {
  @Published var users: [User]
  @Published var category: String
  init(category: String) {
    self.category = continentcategory
    self.users = UserData().getUsers(byCategory: category)
  }
}  

UserData is the Data Model where I have a function getUsers(byCategory) that allows me to get a subset of data instead of all data and then filtering it.

For my SwiftUI view

//UserListByCategory.swift

import SwiftUI
struct UserListByCategory: View {
    @EnvironmentObject var ud: UsersViewModel
    var body: some View {
        Text("Hello")
    }
}

struct UserListByCategory_Previews: PreviewProvider {
    static var previews: some View {
        UserListByCategory()
            .environmentObject(UsersViewModel(category: "Office"))
    }
}

This above SwiftUI View gets called by another ListView after the user selects a category. How do I pass that category without hardcoding it here?

CodePudding user response:

In SwiftUI we don't use view model objects for our view data. View structs are our primary encapsulation mechanism, e.g.

If you need to fetch your data:

struct UserListByCategory: View {

    let category: String
    @State var users: [User] = []

    var body: some View {
        List {
            ForEach(users) { user in
                Text("\(user.name)")
            }
        }
        .task(id: category) {
            users = await fetchUsers(category: category)
        }
    }
}

struct UserListByCategory_Previews: PreviewProvider {
    static var previews: some View {
        UserListByCategory(category: "Office")
    }
}

If you already have all the model data, pass it down the View struct hierarchy as follows:

struct ContentView: View {
    @ObservedObject var model: Model
    var body: some View {
        UserList(users: model.users(category:"Office"))
    }
}

struct UserList: View {
    let users: [User]

    var body: some View {
        List {
            ForEach(users) { user in
                Text("\(user.name)")
            }
        }
    }
}

CodePudding user response:

The answer was to create a ViewModelFactory This link https://mokacoding.com/blog/swiftui-dependency-injection/#view-models-view-model-factory was extremely helpful in setting up my app with ViewModels for each View and set up a Factory that allowed me for navigation and do Dependency Injections.

  •  Tags:  
  • Related