I have 2 Views inside a TabView
(each view is in a different view file):
- For adding employees (AddEmployeeView.swift)
- For displaying employees (AllEmployeesView.swift)
and I also have a View Model in EmployeeDB.swift .
I want to use the same object ( @StateObject var viewModel = EmployeeViewModel()
) from AddEmployeeView.swift to access and display viewModel 's info in AllEmployeesView.swift. I tried
using @ObservedObject
to do so which is working, but when I initialize this view (AllEmployeesView()
)in TabView
this error ( Missing argument for parameter 'viewModel' in call ) pops up.
How can I access the updated data like AddEmployeeView
's viewModel.allEmployees
from the AllEmployeesView
View?
ContentView.swift
struct ContentView: View {
var body: some View {
TabView() {
AddEmployeeView()
.tabItem {
Text("Add")
}
AllEmployeesView() //Missing argument for parameter 'viewModel' in call
.tabItem {
Text("All Employee")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
EmployeeDB.swift
class EmployeeViewModel: ObservableObject {
var allEmployees = [Employee]()
@Published var name : String = ""
@Published var id : String = ""
struct Employee: Identifiable {
let name : String
let id: String
}
func save() {
let newEmployee = Employee(name: name, id: id)
allEmployees.append(newEmployee)
}
func getEmployees() -> [Employee] {
return allEmployees
}
}
AddEmployeeView.swift
struct AddEmployeeView: View {
@StateObject var viewModel = EmployeeViewModel()
var body: some View {
VStack {
TextField("Name", text: $viewModel.name)
TextField("Id", text: $viewModel.id)
Button ("Save") {
viewModel.save()
}
}
.background(.gray)
.padding()
}
}
struct AddEmployeeView_Previews: PreviewProvider {
static var previews: some View {
AddEmployeeView()
}
}
AllEmployeesView.swift
struct AllEmployeesView: View {
@ObservedObject var viewModel: EmployeeViewModel
var body: some View {
List {
let allEmployees = viewModel.allEmployees
ForEach(allEmployees) { employee in
Text(employee.name)
}
}
}
}
struct AllEmployeesView_Previews: PreviewProvider {
static var previews: some View {
AllEmployeesView(viewModel: EmployeeViewModel())
}
}
CodePudding user response:
You should have one source of truth for your viewModel
.
Create your viewModel
as a @StateObject
in ContentView
and pass it to AddEmployeeView
and AllEmployeesView
.
In order to do that, declare:
@ObservedObject var viewModel: EmployeeViewModel
in both AddEmployeeView
and AllEmployeesView
. Then pass in viewModel
from ContentView
like this:
AddEmployeeView(viewModel: viewModel)
and
AllEmployeesView(viewModel: viewModel)
That way, all three of your views will be working from the same viewModel
which keeps everything in sync.