Home > Mobile >  Can ForEach integrate over an array within an array?
Can ForEach integrate over an array within an array?

Time:11-13

I'm building an app that shows company "x" pay rates for different departments within the company. The problem I'm running into is being able to create a ForEach that will iterate over all the pay rate array data. Currently, when you click on "Development", "Training" or "Marketing" the pay rates that display are for "Development." The higher pay rates for "Training" and "Marketing" do not display. My model data is organized to be an array ([Dept]) of arrays ([rates]). I have not been able to find any documentation or tutorials that explain how to iterate over an array within an array.

Here is my PayRateDetailView:

struct RateDetailView: View {
var dept: Dept

var body: some View {
        List {
            ForEach(dept.rates) { line in
                RateCardView(dept: dept)
            }
        }
        .navigationTitle(dept.deptName)
}
}

Here is my RateCardView:

struct RateCardView: View {
var dept: Dept

var body: some View {
    ForEach(dept.rates) { rate in
        HStack {
            Text("Year \(rate.year)")
            Spacer()
            Text("$ \(rate.shiftWorkerRate, specifier: "%.2f")")
            Spacer()
            Text("$ \(rate.managerRate, specifier: "%.2f")")
        }
    }
}
}

Here is my PayRateView:

struct PayRateView: View {
var depts: [Dept]
var dept: Dept

var body: some View {
    List {
        ForEach(depts, id: \.deptName) { name in
            NavigationLink(destination:
                            RateCardView(dept: dept)) {
                Label(name.deptName, systemImage: "person")
            }
        }
    }
}
}

I'm thinking the answer to my problem may be in finding a better way to display my pay rate model data, but this is the structure that seems best for what I'm trying to display:

struct Dept: Identifiable {
let id: UUID
var deptName: String
var rates: [HourlyRates]

init(id: UUID = UUID(), deptName: String, rates: [HourlyRates]) {
    self.id = id
    self.deptName = deptName
    self.rates = rates
}
}
extension Dept {
static let deptList: [Dept] = [
    Dept(deptName: "Development", rates: [
        HourlyRates(year: 1, shiftWorkerRate: 10, managerRate: 20),
        HourlyRates(year: 2, shiftWorkerRate: 11, managerRate: 21),
        HourlyRates(year: 3, shiftWorkerRate: 12, managerRate: 22),
        HourlyRates(year: 4, shiftWorkerRate: 13, managerRate: 23),
        HourlyRates(year: 5, shiftWorkerRate: 14, managerRate: 24),
        HourlyRates(year: 6, shiftWorkerRate: 15, managerRate: 25),
        HourlyRates(year: 7, shiftWorkerRate: 16, managerRate: 26)]),
    Dept(deptName: "Training", rates: [
        HourlyRates(year: 1, shiftWorkerRate: 12, managerRate: 22),
        HourlyRates(year: 2, shiftWorkerRate: 13, managerRate: 23),
        HourlyRates(year: 3, shiftWorkerRate: 14, managerRate: 24),
        HourlyRates(year: 4, shiftWorkerRate: 15, managerRate: 25),
        HourlyRates(year: 5, shiftWorkerRate: 16, managerRate: 26),
        HourlyRates(year: 6, shiftWorkerRate: 17, managerRate: 27),
        HourlyRates(year: 7, shiftWorkerRate: 18, managerRate: 28)]),
    Dept(deptName: "Marketing", rates: [
        HourlyRates(year: 1, shiftWorkerRate: 12, managerRate: 22),
        HourlyRates(year: 2, shiftWorkerRate: 13, managerRate: 23),
        HourlyRates(year: 3, shiftWorkerRate: 14, managerRate: 24),
        HourlyRates(year: 4, shiftWorkerRate: 15, managerRate: 25),
        HourlyRates(year: 5, shiftWorkerRate: 16, managerRate: 26),
        HourlyRates(year: 6, shiftWorkerRate: 17, managerRate: 27),
        HourlyRates(year: 7, shiftWorkerRate: 18, managerRate: 28)])
]
}

struct HourlyRates: Identifiable {
let id: UUID
var year: Int
var shiftWorkerRate: Double
var managerRate: Double

init(id: UUID = UUID(), year: Int, shiftWorkerRate: Double, managerRate: Double) {
    self.id = id
    self.year = year
    self.shiftWorkerRate = shiftWorkerRate
    self.managerRate = managerRate
}
}

CodePudding user response:

All works well for me, without using the RateDetailView that you call PayRateDetailView, and minor mods in PayRateView.

Here is my test code, that shows the "Development", "Training" and "Marketing" pay rates are displayed as expected.

struct ContentView: View {
    var body: some View {
        NavigationStack {  // <-- here
            PayRateView()
        }
    }
}

struct RateCardView: View {
    var dept: Dept
    
    var body: some View {
        ForEach(dept.rates) { rate in
            HStack {
                Text("Year \(rate.year)")
                Spacer()
                Text("$ \(rate.shiftWorkerRate, specifier: "%.2f")")
                Spacer()
                Text("$ \(rate.managerRate, specifier: "%.2f")")
            }
        }
    }
}

struct PayRateView: View {
    var depts: [Dept] = Dept.deptList
    var dept: Dept = Dept(deptName: "", rates: [])
    
    var body: some View {
        List {
            ForEach(depts, id: \.deptName) { dept in  // <-- here
                NavigationLink(destination: RateCardView(dept: dept)) {
                    Label(dept.deptName, systemImage: "person")  // <-- here
                }
            }
        }
    }
}

struct Dept: Identifiable {
    let id: UUID
    var deptName: String
    var rates: [HourlyRates]
    
    init(id: UUID = UUID(), deptName: String, rates: [HourlyRates]) {
        self.id = id
        self.deptName = deptName
        self.rates = rates
    }
}

extension Dept {
    
    // here for testing
    static let deptList: [Dept] = [
        Dept(deptName: "Development", rates: [
            HourlyRates(year: 1, shiftWorkerRate: 0, managerRate: 20),
            HourlyRates(year: 2, shiftWorkerRate: 0, managerRate: 21),
            HourlyRates(year: 3, shiftWorkerRate: 0, managerRate: 22),
            HourlyRates(year: 4, shiftWorkerRate: 0, managerRate: 23),
            HourlyRates(year: 5, shiftWorkerRate: 0, managerRate: 24),
            HourlyRates(year: 6, shiftWorkerRate: 0, managerRate: 25),
            HourlyRates(year: 7, shiftWorkerRate: 0, managerRate: 26)]),
        Dept(deptName: "Training", rates: [
            HourlyRates(year: 1, shiftWorkerRate: 1, managerRate: 22),
            HourlyRates(year: 2, shiftWorkerRate: 1, managerRate: 23),
            HourlyRates(year: 3, shiftWorkerRate: 1, managerRate: 24),
            HourlyRates(year: 4, shiftWorkerRate: 1, managerRate: 25),
            HourlyRates(year: 5, shiftWorkerRate: 1, managerRate: 26),
            HourlyRates(year: 6, shiftWorkerRate: 1, managerRate: 27),
            HourlyRates(year: 7, shiftWorkerRate: 1, managerRate: 28)]),
        Dept(deptName: "Marketing", rates: [
            HourlyRates(year: 1, shiftWorkerRate: 2, managerRate: 22),
            HourlyRates(year: 2, shiftWorkerRate: 2, managerRate: 23),
            HourlyRates(year: 3, shiftWorkerRate: 2, managerRate: 24),
            HourlyRates(year: 4, shiftWorkerRate: 2, managerRate: 25),
            HourlyRates(year: 5, shiftWorkerRate: 2, managerRate: 26),
            HourlyRates(year: 6, shiftWorkerRate: 2, managerRate: 27),
            HourlyRates(year: 7, shiftWorkerRate: 2, managerRate: 28)])
    ]
}

struct HourlyRates: Identifiable {
    let id: UUID
    var year: Int
    var shiftWorkerRate: Double
    var managerRate: Double
    
    init(id: UUID = UUID(), year: Int, shiftWorkerRate: Double, managerRate: Double) {
        self.id = id
        self.year = year
        self.shiftWorkerRate = shiftWorkerRate
        self.managerRate = managerRate
    }
}
  • Related