You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
}
}

错误原因分析

  1. PayRateView传参错误:遍历depts数组时,NavigationLink传递的是固定的dept参数,而非当前遍历的name对象,导致所有导航链接都指向同一个部门的数据。
  2. 视图职责混乱与重复遍历: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 08:42:22