SwiftUI中如何用ForEach遍历嵌套数组?薪资展示异常排查
解决SwiftUI中嵌套数组遍历与部门薪资展示错误问题
问题场景
开发X公司各部门薪资展示App时,遇到以下问题:
- 点击“Development”“Training”或“Marketing”任一部门,均只显示Development部门的薪资数据,无法正确展示Training和Marketing部门的更高薪资。
- 视图存在重复遍历数组的冗余逻辑,导致显示混乱。
数据模型为嵌套数组结构:[Dept]数组中包含[rates]数组,原代码如下:
原RateDetailView
struct RateDetailView: View { var dept: Dept var body: some View { List { ForEach(dept.rates) { line in RateCardView(dept: dept) } } .navigationTitle(dept.deptName) } }
原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")") } } } }
原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") } } } } }
数据模型
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 } }
错误原因分析
- PayRateView传参错误:遍历
depts数组时,NavigationLink传递的是固定的dept参数,而非当前遍历的name对象,导致所有导航链接都指向同一个部门的数据。 - 视图职责混乱与重复遍历:
RateDetailView遍历dept.rates后嵌套RateCardView,而RateCardView又再次遍历dept.rates,造成每个薪资条目重复渲染整个部门的所有数据,既冗余又导致显示逻辑错误。
修正后的代码
1. 重构RateCardView(专注单条薪资展示)
将视图调整为接收单个HourlyRates对象,负责展示单一年份的薪资数据:
struct RateCardView: View { var rate: HourlyRates var body: some View { HStack { Text("Year \(rate.year)") Spacer() Text("$ \(rate.shiftWorkerRate, specifier: "%.2f")") Spacer() Text("$ \(rate.managerRate, specifier: "%.2f")") } } }
2. 修正RateDetailView(遍历部门薪资条目)
负责遍历当前部门的所有薪资条目,逐个传递给RateCardView:
struct RateDetailView: View { var dept: Dept var body: some View { List { ForEach(dept.rates) { rate in RateCardView(rate: rate) } } .navigationTitle(dept.deptName) } }
3. 修正PayRateView(正确传递部门数据)
移除冗余的dept参数,遍历depts时将当前部门对象传递给详情页:
struct PayRateView: View { var depts: [Dept] var body: some View { List { ForEach(depts) { dept in NavigationLink(destination: RateDetailView(dept: dept)) { Label(dept.deptName, systemImage: "person") } } } } }
修正要点说明
- PayRateView:移除固定的
dept参数,确保每个导航链接对应当前遍历的部门对象,解决所有链接指向同一部门的问题。 - RateCardView:调整为接收单个薪资条目,明确视图职责,避免重复遍历数组。
- RateDetailView:负责部门薪资列表的遍历与渲染,与
RateCardView形成清晰的职责划分,消除冗余逻辑。
内容的提问来源于stack exchange,提问作者weekendwarrior
相关产品推荐
相关产品推荐

