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")
}

Вот скриншот представления карты с фиктивными данными:

Вот скриншот ContentView, который не принимает ввод:

Вот ошибка, которую я получаю в EmployeeCardView_Preview:

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))
     }
 }
Другие вопросы по тегам