I have this view, for example:
struct MyChartView: View {
let chart: MyChart
@State private var selectedPoint: Int? = nil
var body: some View {
//... draw chart, set/move selectedPoint by a gesture ...
}
.onChange(of: chart) { selectedPoint = nil }
}
How to reset selectedPoint var when the view is reinitialized with new chart and before the render pass happens? onChange triggers after the first render pass and it causes inconsistency, since chart already contains new value that was passed to init(). I couldn't find any by-design approaches, and from what I've tried only this hack works:
Introduce a state var for chart hash and compare it each time with new hash in render pass. If it doesn't match, skip the render:
@State private var chartHash: Int
var body: some View {
let newChartHash = computeChartsHash(chart)
if newChartHash != self.chartHash {
return
}
...
onChangecause? This sounds like an XY Problem. You could use thechartitself as theidof the view, and that would destroy and recreate the whole view, including its state. You could also changeselectedPointto include information about which chart it is for, so that an "invalid" selection can be easily detected, which is similar to your approach using a hash.selectedPointreset before the very first render pass with newchartvalue. I just tried your idea with view id - so far the same result. The other option to include more info inselectedPointlooks good...selectedPointdoesn't "getselectedPointreset before the very first render pass" (your definition of a "correct solution") though, but you say it "looks good". In any case, I believe you should be fixing the "inconsistency", and not worry about render passes. That is, makebodystill produce a "consistent" view even ifselectedPointis invalid. You would check ifselectedPointis valid and if it is not, treat it asnil. Without further details though, I can't tell you exactly how to implement this.