Как вставлять функции в массив с помощью пользовательских опубликованных переменных

Вот желаемый результат (список из viewModel, полученный с использованием функций для ежегодного повышения заработной платы и отображения возраста пользователя из года в год). Когда пользователь изменяет дату своего рождения и дату приема на работу в ProfileFormView, этот список должен соответствующим образом обновить группу «Возраст и год»:

К сожалению, мне не удалось успешно создать это представление из-за ошибок при попытках включить функции в массив viewModel.

Вот моя модель просмотра:

      class WorkerViewModel:ObservableObject {

@Published var userData: Worker =
Worker(name: "Robert", birthdate: Date(timeIntervalSince1970: 10000), hiredate: Date(timeIntervalSince1970: 30000), department: "HR")

func calcAge(birthdate: String) -> Int {
    let dateFormater = DateFormatter()
    dateFormater.dateFormat = "MM/dd/yyyy"
    let birthdayDate = dateFormater.date(from: birthdate)
    let calendar: NSCalendar! = NSCalendar(calendarIdentifier: .gregorian)
    let now = Date()
    let calcAge = calendar.components(.year, from: birthdayDate!, to: now, options: [])
    let age = calcAge.year
    return age!
}
    
func calcYearGroup(hiredate: String) -> Int {
    let dateFormater = DateFormatter()
    dateFormater.dateFormat = "MM/dd/yyyy"
    let newHireDateFormatted = dateFormater.date(from: hiredate)
    let calendar: NSCalendar! = NSCalendar(calendarIdentifier: .gregorian)
    let now = Date()
    let calcYearGroup = calendar.components(.year, from: newHireDateFormatted!, to: now, options: [])
    let yearGroup = calcYearGroup.year! + 1
    return yearGroup
}
    
func calcAnnualEarnings(hourlyRate: Double, monthlyHours: Double) -> Double {
    return (hourlyRate * monthlyHours) * 12
}
    
 @Published var userDataList: [WorkerInfo] = [
    WorkerInfo(age: calcAge(birthdate: $WorkerInfo.birthdate), yearGroup: calcYearGroup(hiredate: $WorkerInfo.hiredate), salary: calcAnnualEarnings(hourlyRate: PayRates.hR[1], monthlyHours: 72), dept: "\($WorkerInfo.department)"),
    WorkerInfo(age: calcAge(birthdate: $WorkerInfo.birthdate) + 1, yearGroup: calcYearGroup(hiredate: $WorkerInfo.hiredate)  + 1, salary: calcAnnualEarnings(hourlyRate: PayRates.hR[2], monthlyHours: 72), dept: "\($WorkerInfo.department)"),
    WorkerInfo(age: calcAge(birthdate: $WorkerInfo.birthdate) + 2, yearGroup: calcYearGroup(hiredate: $WorkerInfo.hiredate) + 2, salary: calcAnnualEarnings(hourlyRate: PayRates.hR[3], monthlyHours: 72), dept: "\($WorkerInfo.department)"),
    WorkerInfo(age: calcAge(birthdate: $WorkerInfo.birthdate) + 3, yearGroup: calcYearGroup(hiredate: $WorkerInfo.hiredate) + 3, salary: calcAnnualEarnings(hourlyRate: PayRates.hR[4], monthlyHours: 72), dept: "\($WorkerInfo.department)"),
    WorkerInfo(age: calcAge(birthdate: $WorkerInfo.birthdate) + 4, yearGroup: calcYearGroup(hiredate: $WorkerInfo.hiredate) + 4, salary: calcAnnualEarnings(hourlyRate: PayRates.hR[5], monthlyHours: 72), dept: "\($WorkerInfo.department)"),
]
}

Вот данные моей модели:

      struct Worker: Codable, Identifiable {
var id = UUID()
var name: String
var birthdate: Date
var hiredate: Date
var department: String
}

struct WorkerInfo: Codable, Identifiable {
var id = UUID()
var age: Int
var yearGroup: Int
var salary: Double
var dept: String
}

struct MockData {

static let sampleUser = WorkerInfo(age: 41, yearGroup: 1, salary: 80000, dept: "HR")
}

struct PayRates {
let hR: [Double] = [0,92,128,150,154,158,162,166,170,172,174,177,180]
let management: [Double] = [0,235,236,238,240,242,244,246,248,250,252,254,256]
}

Вот мой вид контента:

      struct ContentView: View {
@StateObject var vm = WorkerViewModel()

var body: some View {
    TabView {
        ProfileFormView()
            .tabItem {
                Image(systemName: "square.and.pencil")
                Text("Profile")
            }
        WorkerView()
            .tabItem {
                Image(systemName: "house")
                Text("Home")
            }
            .padding()
    }.environmentObject(vm)
}
}

Вот мой рабочий вид:

      struct WorkerView: View {
@EnvironmentObject var vm: WorkerViewModel

var body: some View {
    ZStack {
        List($vm.userDataList) { $worker in
            WorkerCardView(workerInfo: $worker)
        }
    }
}
}

Вот мой вид ProfileForm:

      struct ProfileFormView: View {
@EnvironmentObject var vm: WorkerViewModel
@State var depts = ["HR","Management","Marketing","Development"]

var body: some View {
    Form {
        Section(header: Text("Personal Information")) {
            TextField("Name", text: $vm.userData.name)
            DatePicker("Birthdate", selection: $vm.userData.birthdate, displayedComponents: .date)
            DatePicker("New Hire Date", selection: $vm.userData.hiredate, displayedComponents: .date)
            Picker("Department", selection: $vm.userData.department) {
                ForEach(depts, id: \.self) {
                    Text ($0)
                }
            }
        }
    }
}
}

И, наконец, вот мой WorkerCard View:

      struct WorkerCardView: View {
@Binding var workerInfo: WorkerInfo

var body: some View {
    HStack{
        VStack(alignment: .leading) {
            Text("Year \(workerInfo.yearGroup)")
                .font(.headline)
            Label("Age \(workerInfo.age)", systemImage: "person")
                .foregroundStyle(.blue)
                .font(.subheadline)
        }
        Spacer()
        VStack(alignment: .leading) {
            Text("$ \(workerInfo.salary, specifier: "%.0f") salary")
                .font(.headline)
            Label("\(workerInfo.dept) Dept", systemImage: "building")
                .foregroundStyle(.blue)
                .font(.subheadline)
        }
    }
}
}

Заранее спасибо за вашу помощь!!

//ОБНОВЛЕНИЕ 1//

Я преобразовал свои функции в вычисляемые свойства, казалось бы, без ошибок. Это также имеет дополнительное преимущество, заключающееся в том, что код становится чище, что приятно.

Теперь я свел проблему к проблеме инициализации. Каждое из трех моих вычисляемых свойств вызывает ошибки компилятора при помещении в массив userDataList:

«Невозможно использовать член экземпляра 'computedProperty' в инициализаторе свойства; инициализаторы свойств запускаются до того, как становится доступным 'self'»

//ОБНОВЛЕНИЕ 2//

Я преобразовал userDataArray в вычисляемое свойство, но результирующая ошибка компилятора связана с оболочкой свойства @Published. Естественно, вычисляемые свойства не могут получать обертки свойств, но мне нужно, чтобы userDataArray был виден для WorkerView, чтобы список мог перебирать userDataArray.

Удаление @Published вызывает эту ошибку компилятора в WorkerView:

"Невозможно присвоить свойству: "userDataList" является свойством только для получения"

0 ответов

Другие вопросы по тегам