WWDC24 SALE: Save 50% on all my Swift books and bundles! >>

SOLVED: Transitioning from Command Line Tool -> iOS app: Using viewModel to communicate between views

Forums > Swift

I'm very grateful for all the help that this friendly community has provided me over the past few weeks! I think it is time to start transitioning my employee-promotion project from a Command Line Tool project to an iOS app project.

Here is the GitHub repository which contains both the working Command Line Tool and my iOS app framework.

Specific challenge to overcome: learn what coding principle is appropriate to apply to the ForEach loop in the Results tab of the iOS app.

In Command Line Tool, the following code provided print results showing promotions and income changes:

var charlotte = Employee("Charlotte Grote", birthdate: birthdate, hiredate: hiredate, retirementAge: 65, department: .other("Hospitality"), monthlyHoursWorked: 160, regularPayRateIncreases: true, regularPayRateIncreasePercentage: 4, regularPayRateIncreaseYearInterval: 4)
//give our employee some work history
//months in Hospitality
charlotte.work(months: firstDeptMonths)
//ohh, a promotion!
charlotte.promote(to: .sales)
//months in Sales
charlotte.work(months: secondDeptMonths)
//another promotion. way to go, Charlotte!
charlotte.promote(to: .management)
//months in Management
charlotte.work(months: thirdDeptMonths)
//another promotion. way to go, Charlotte!
charlotte.promote(to: .seniorManagement)
//months in Senior Management
charlotte.work(months: fourthDeptMonths)
printYearlyDepartmentsAndEarnings(charlotte.yearlyDepartmentsEarnings())

In my iOS app framework I have a ProfileFormView which enables the user to select their current department, monthly hours , etc. I have a ResultsView where I want to show the results. And I have a viewModel which should contain the back-end communication/formulae between the two.

What I don't know is how to translate the above Command Line Tool code into the viewModel in a package that is readable by the ForEach loop of the ResultsView.

My current ResultsView also contains a struct of SampleData expressly for the purpose of showing how I would like the true user data to be displayed.

In the past I've used a computed property array but that was burdensome and massive. I'm hoping y'all could point me in the direction toward a coding principle that facilitates a more streamlined process. Perhaps provide an example I could replicate.

2      

I have made some progress but still need help. My GitHub repository is updated with new Employee model and EmployeeViewModel

I'm having difficulty finding the right place to put my retireDate constant. Here is the EmployeeViewModel code:

class EmployeeViewModel: ObservableObject {

    @Published var userData: Employee =
    Employee("Charlotte Grote", 
    birthdate: DateComponents(calendar: .current, year: 1965, month: 7, day: 20).date!, 
    hiredate: DateComponents(calendar: .current, year: 2021, month: 12, day: 28).date!, 
    yearGroup: 1, retirementAge: 65, department: .other("Hospitality"), 
    monthlyHoursWorked: 160, 
    planningToPromote1: true, 
    planningToPromote2: false, 
    planningToPromote3: false, 
    planningToPromote4: false, 
    promotion1Date: DateComponents(calendar: .current, year: 2023, month: 12, day: 28).date!, 
    promotion2Date: DateComponents(calendar: .current, year: 2025, month: 6, day: 28).date!, 
    promotion3Date: DateComponents(calendar: .current, year: 2026, month: 12, day: 28).date!, 
    regularPayRateIncreases: true, 
    regularPayRateIncreasePercentage: 4, 
    regularPayRateIncreaseYearInterval: 4)

    var firstDeptMonths: Int { Calendar.current.dateComponents([.month], from: userData.hiredate, to: userData.promotion1Date).month! }
    var secondDeptMonths: Int { Calendar.current.dateComponents([.month], from: userData.promotion1Date, to: userData.promotion2Date).month! }
    var thirdDeptMonths: Int { Calendar.current.dateComponents([.month], from: userData.promotion2Date, to: userData.promotion3Date).month! }
    let retireDate = Calendar.current.date(byAdding: .year, value: userData.retirementAge, to: userData.birthdate)!  //2 errors here
    var fourthDeptMonths: Int { Calendar.current.dateComponents([.month], from: userData.promotion3Date, to: retireDate).month! }
}

extension Date {
    var age: Int { Calendar.current.dateComponents([.year], from: self, to: Date()).year! }
    var yearGroup: Int { Calendar.current.dateComponents([.year], from: self, to: Date()).year! + 1}
    var totalYearsRemaining: Int { Calendar.current.dateComponents([.year], from: self, to: retireDate).year! } //3rd error here
    var totalMonthsRemaining: Int { Calendar.current.dateComponents([.month], from: self, to: retireDate).month! } //4th error here
}

The errors are:

  1. Cannot use instance member 'userData' within property initializer; property initializers run before 'self' is available
  2. Cannot use instance member 'userData' within property initializer; property initializers run before 'self' is available
  3. Cannot find 'retireDate' in scope
  4. Cannot find 'retireDate' in scope

2      

Hi, I opened the EmployeeModel and the EmployeeViewModel and EmployeeViewModel is giving me a few errors

Value of type 'Employee' has no member 'promotion1Date' Value of type 'Employee' has no member 'promotion2Date' Value of type 'Employee' has no member 'promotion3Date'

I was able to remove the other 4 errors making the following changes: for the first 2 errors i changed the let to a computed property:

    var retireDate: Date { Calendar.current.date(byAdding: .year, value: userData.retirementAge, to: userData.birthdate)! }

for the other 2 it should read EmployeeViewModel().retireDate:

    var totalYearsRemaining: Int { Calendar.current.dateComponents([.year], from: self, to: EmployeeViewModel().retireDate).year! }
    var totalMonthsRemaining: Int { Calendar.current.dateComponents([.month], from: self, to: EmployeeViewModel().retireDate).month! }

Hope it helps

3      

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.