SwiftUI: представление не обновляется при вводе данных пользователем в полях/средствах выбора формы
Кажется, я не могу обновить свой «Представление сотрудника» на основе пользовательского ввода в форме внутри «ProfileFormView». В настоящее время любой ввод в поля формы не влияет на «EmployeeView». Мне нужны данные, которые вводятся в форму, чтобы обновить «Представление сотрудника». Где я неправ?
Вот моя модель просмотра:
@MainActor class EmployeeViewModel: ObservableObject {
@Published var name = ""
@Published var empNum = ""
@Published var birthdate = Date(timeIntervalSince1970: 0)
@Published var dept = ""
@Published var userData: [Employee] = []
init(name: String = "", empNum: String = "", birthdate: Date = Date(timeIntervalSince1970: 0), dept: String = "", userData: [Employee] = []) {
self.name = name
self.empNum = empNum
self.birthdate = birthdate
self.dept = dept
self.userData = [
Employee(birthdate: birthdate, name: name, empNum: empNum, department: dept)]
}
}
Вот мой вид сотрудников:
struct EmployeeView: View {
let viewModel: EmployeeViewModel
var body: some View {
ZStack {
VStack {
List(viewModel.userData, id: \.id) { line in
EmployeeCardView(employee: line)
}
}
}
}
}
Вот мой ProfileFormView:
struct ProfileFormView: View {
@EnvironmentObject var viewModel: EmployeeViewModel
@State var depts = ["HR","Management","Marketing","Development"]
var body: some View {
NavigationView {
Form {
Section(header: Text("Personal Information")) {
TextField("Name", text: $viewModel.name)
DatePicker("Birthdate", selection: $viewModel.birthdate, displayedComponents: .date)
TextField("Employee #", text: $viewModel.empNum)
Picker("Department", selection: $viewModel.dept) {
ForEach(depts, id: \.self) {
Text ($0)
}
}
}
}
}
}
}
Вот мой ContentView(обратите внимание, что два представления являются вкладками в ContentView):
struct ContentView: View {
@StateObject var vm = EmployeeViewModel()
var body: some View {
NavigationView {
ZStack {
Color.gray.ignoresSafeArea()
.navigationBarHidden(true)
TabView {
ProfileFormView()
.tabItem {
Image(systemName: "square.and.pencil")
Text("Profile")
}
EmployeeView(viewModel: EmployeeViewModel())
.tabItem {
Image(systemName: "house")
Text("Home")
}
.padding()
}
.environmentObject(vm)
}
}
}
}
Вот мой вид карты:
struct EmployeeCardView: View {
let employee: Employee
var body: some View {
ZStack{
VStack {
HStack() {
Spacer()
Text(employee.name)
.foregroundStyle(.blue)
.font(.headline)
Spacer()
Label("\(employee.birthdate.formatted(date: .abbreviated, time: .omitted))", systemImage: "calendar")
.foregroundStyle(.blue)
.font(.subheadline)
Spacer()
}
HStack() {
Spacer()
Label("\(employee.empNum)", systemImage: "person")
.foregroundStyle(.blue)
.font(.subheadline)
Spacer()
Label("\(employee.department)", systemImage: "building")
.foregroundStyle(.blue)
.font(.subheadline)
Spacer()
}
}
}
}
}
Вот моя модель данных:
struct Employee: Codable, Identifiable {
var id = UUID()
var birthdate = Date(timeIntervalSince1970: 0)
var name = ""
var empNum = "8675309"
var department = ""
init(id: UUID = UUID(), birthdate: Date = Date(timeIntervalSince1970: 0), name: String = "", empNum: String = "8675309", department: String = "") {
self.id = id
self.birthdate = birthdate
self.name = name
self.empNum = empNum
self.department = department
}
}
struct MockData {
static let mockData = [sampleUser,sampleUser, sampleUser]
static let sampleUser = Employee(birthdate: Date(timeIntervalSince1970: 0), name: "Bob", empNum: "8675309", department: "HR")
}
Вот скриншот представления карты с фиктивными данными:
1 ответ
Попробуйте этот подход, используя@EnvironmentObject
чтобы передать модель представления вокруг, и@Binding
в . Работает для меня:
struct EmployeeCardView: View {
@Binding var employee: Employee
var body: some View {
VStack {
HStack() {
Spacer()
Text(employee.name)
.foregroundStyle(.blue)
.font(.headline)
Spacer()
Label("\(employee.birthdate.formatted(date: .abbreviated, time: .omitted))", systemImage: "calendar")
.foregroundStyle(.blue)
.font(.subheadline)
Spacer()
}
HStack() {
Spacer()
Label("\(employee.empNum)", systemImage: "person")
.foregroundStyle(.blue)
.font(.subheadline)
Spacer()
Label("\(employee.department)", systemImage: "building")
.foregroundStyle(.blue)
.font(.subheadline)
Spacer()
}
}
}
}
struct EmployeeView: View {
@EnvironmentObject var vm: EmployeeViewModel
var body: some View {
List($vm.userData) { $employee in
EmployeeCardView(employee: $employee)
}
}
}
struct ProfileFormView: View {
@EnvironmentObject var vm: EmployeeViewModel
@State var depts = ["HR","Management","Marketing","Development"]
var body: some View {
Form {
ForEach($vm.userData) { $employee in
Section(header: Text("Personal Information")) {
TextField("Name", text: $employee.name)
DatePicker("Birthdate", selection: $employee.birthdate, displayedComponents: .date)
TextField("Employee #", text: $employee.empNum)
Picker("Department", selection: $employee.department) {
ForEach(depts, id: \.self) {
Text($0)
}
}
}
}
}
}
}
struct ContentView: View {
@StateObject var vm = EmployeeViewModel()
var body: some View {
ZStack {
Color.gray.ignoresSafeArea()
TabView {
ProfileFormView()
.tabItem {
Image(systemName: "square.and.pencil")
Text("Profile")
}
EmployeeView()
.tabItem {
Image(systemName: "house")
Text("Home")
}
.padding()
}.environmentObject(vm)
}
}
}
struct Employee: Codable, Identifiable {
var id = UUID()
var birthdate: Date
var name: String
var empNum: String
var department: String
}
class EmployeeViewModel: ObservableObject {
@Published var userData: [Employee] = [
Employee(birthdate: Date(timeIntervalSince1970: 0), name: "Bob", empNum: "8675309", department: "HR"),
Employee(birthdate: Date(timeIntervalSince1970: 10000), name: "Jack", empNum: "123456", department: "Marketing"),
Employee(birthdate: Date(timeIntervalSince1970: 60000), name: "Albert", empNum: "87425", department: "HR")
]
}
РЕДАКТИРОВАТЬ-1: сPreviews
дляEmployeeCardView
struct EmployeeCardView_Previews: PreviewProvider {
static var previews: some View {
EmployeeCardView(employee: .constant(MockData.sampleUser))
}
}