I have a List
in which each cell has a chart. The data for the list is generated once and stored in the chartData
property. However, there is a bug. When scrolling the list, the charts in the cells change places: if we scroll the list a couple of cells down and then return to the top, then the first cell will have a completely different chart from what was before scrolling. However, only the chart changes, the number Text
remains unchanged
struct ChartData: Identifiable {
let id = UUID()
let number: Int
let data: [Double]
var isPositiveTrend: Bool {
return data.last ?? 0 > data.first ?? 0
}
}
struct ContentView: View {
let chartData: [ChartData] = (0..<90).map { index in
ChartData(number: index, data: (0..<12).map { _ in Double.random(in: 1...10) })
}
var body: some View {
List {
ForEach(chartData) { data in
HStack {
Text("\(data.number)")
Chart(Array(zip(data.data.indices, data.data)), id: \.0) { idx, val in
LineMark(
x: .value("index", idx),
y: .value("value", val)
)
.interpolationMethod(.catmullRom)
.foregroundStyle(data.isPositiveTrend ? .green : .red)
}
.chartYScale(domain: .automatic(includesZero: false))
.chartYAxis(.hidden)
.chartXAxis(.hidden)
.chartLegend(.hidden)
}
}
}
}
}
It seems that it is a bug appears from iOS 17.4 (See https://forums.developer.apple.com/forums/thread/750052)
According to the discussion above:
Adding .id(VALUE) to Chart(), where VALUE is unique per Chart()
will solve the issue
struct ChartData: Identifiable {
let id = UUID()
let number: Int
let data: [Double]
var isPositiveTrend: Bool {
return data.last ?? 0 > data.first ?? 0
}
}
struct ContentView: View {
let chartData: [ChartData] = (0..<90).map { index in
ChartData(number: index, data: (0..<12).map { _ in Double.random(in: 1...10) })
}
var body: some View {
List {
ForEach(chartData) { data in
HStack {
Text("\(data.number)")
Chart(Array(zip(data.data.indices, data.data)), id: \.0) { idx, val in
LineMark(
x: .value("index", idx),
y: .value("value", val)
)
.interpolationMethod(.catmullRom)
.foregroundStyle(data.isPositiveTrend ? .green : .red)
}
.id(data.id) // <-------- ADD THIS
.chartYScale(domain: .automatic(includesZero: false))
.chartYAxis(.hidden)
.chartXAxis(.hidden)
.chartLegend(.hidden)
}
}
}
}
}