The Apple Documentation and all tutorials on Table usage that I've found (example 1 & example 2) build Tables from non-dynamic model arrays.
I have a ViewModel that contains a computed property array (userDataList) which utilized functions and additional computed properties. I'm having difficulty writing the code in the View to make the Table iterate through each of the lines of the userDataList array.
The desired outcome is a Table that has 5 rows (Years 1 through 5) and 3 columns (Year, Annual Income, & 401k Balance) with the Table populated with the appropriate data from the ViewModel userDataList array.
Here is the code:
struct ContentView: View {
@StateObject var vm = ViewModel()
var body: some View {
VStack(spacing: 15){
TabView() {
ProfileView()
.tabItem {
Image(systemName: "square.and.pencil")
Text("Profile")
}
InvestView()
.tabItem {
Image(systemName: "dollarsign")
Text("Tips")
}
}
.environmentObject(vm)
}
}
}
struct ProfileView: View {
var body: some View {
Text("Hello, World!")
}
}
//the ProfileView will eventually have a Form that allows the user to manipulate the values within the userData Published variable within the ViewModel
struct EmployeeInfo: Codable, Identifiable {
var id = UUID()
var monthlyHours: Double
var hourlyRateYear1: Double
var hourlyRateYear2: Double
var hourlyRateYear3: Double
var hourlyRateYear4: Double
var hourlyRateYear5: Double
var startingBalance401k: Double
var contribution: Double
var balance401k: Double
}
struct InvestInfo: Codable, Identifiable {
var id = UUID()
var year: Int
var annualIncome: Double
var balance401k: Double
}
struct Year: Codable, Identifiable {
var id = UUID()
var year: Int
}
struct InvestView: View {
@EnvironmentObject var vm: ViewModel
private let currencyStyle = Decimal.FormatStyle.Currency(code:"USD")
var body: some View {
Table(of: vm.userDataList) {
TableColumn("Years Until Retirement") { item in
Text(item.year)
}
TableColumn("Annual Income") { item in
Text(item.annualIncome), format: currencyStyle)
}
TableColumn("401k Balance") { item in
Text(item.balance401k), format: currencyStyle)
}
} rows: {
TableRow(Year(year: 1))
TableRow(Year(year: 2))
TableRow(Year(year: 3))
TableRow(Year(year: 4))
TableRow(Year(year: 5))
}
}
}
class ViewModel: ObservableObject {
@Published var userData: EmployeeInfo = EmployeeInfo(monthlyHours: 160.0, hourlyRateYear1: 15.0, hourlyRateYear2: 15.0, hourlyRateYear3: 17.0, hourlyRateYear4: 17.0, hourlyRateYear5: 19.0, startingBalance401k: 5000.0, contribution: 5000.0, balance401k: 10000.0)
func calcAnnualEarnings(hourlyRate: Double) -> Double {
return (userData.monthlyHours * hourlyRate) * 12
}
var annualIncomeYear1: Double {
calcAnnualEarnings(hourlyRate: userData.hourlyRateYear1)
}
var annualIncomeYear2: Double {
calcAnnualEarnings(hourlyRate: userData.hourlyRateYear2)
}
var annualIncomeYear3: Double {
calcAnnualEarnings(hourlyRate: userData.hourlyRateYear3)
}
var annualIncomeYear4: Double {
calcAnnualEarnings(hourlyRate: userData.hourlyRateYear4)
}
var annualIncomeYear5: Double {
calcAnnualEarnings(hourlyRate: userData.hourlyRateYear5)
}
func calc401k(princ: Double, deposits: Double) -> Double {
let newRate = 10.0
let rn1 = 1+((newRate/100)/12)
let comp = pow(rn1,12)
let totPrinc = comp * princ
return totPrinc + ((deposits/12) * (comp-1)/((newRate/100)/12))
}
var balanceLine1: Double {
return calc401k(princ:
userData.startingBalance401k, deposits:
userData.contribution)
}
var balanceLine2: Double {
return calc401k(princ:
balanceLine1, deposits:
userData.contribution)
}
var balanceLine3: Double {
return calc401k(princ:
balanceLine2, deposits:
userData.contribution)
}
var balanceLine4: Double {
return calc401k(princ:
balanceLine3, deposits:
userData.contribution)
}
var balanceLine5: Double {
return calc401k(princ:
balanceLine4, deposits:
userData.contribution)
}
var userDataList: [InvestInfo] {
return [
InvestInfo(year: 1, annualIncome: annualIncomeYear1, balance401k: balanceLine1),
InvestInfo(year: 2, annualIncome: annualIncomeYear2, balance401k: balanceLine2),
InvestInfo(year: 3, annualIncome: annualIncomeYear3, balance401k: balanceLine3),
InvestInfo(year: 4, annualIncome: annualIncomeYear4, balance401k: balanceLine4),
InvestInfo(year: 5, annualIncome: annualIncomeYear5, balance401k: balanceLine5)
]
}
}
There errors I receive are within the InvestView:
As you can see, the errors include:
I've tried to treat the Table(of: as a typical ForEach but I am obviously missing something.
try something like this example code, to remove the cascade of errors:
struct InvestView: View {
@EnvironmentObject var vm: ViewModel
private let currencyStyle = Decimal.FormatStyle.Currency(code:"USD")
var body: some View {
Table(vm.userDataList) {
TableColumn("Years Until Retirement") { item in
Text("\(item.year)")
}
TableColumn("Annual Income") { item in
Text(Decimal(item.annualIncome), format: currencyStyle)
}
TableColumn("401k Balance") { item in
Text(Decimal(item.balance401k), format: currencyStyle)
}
}
}
}