How can I include a function (or calculation) in the values that Charts receives to draw the chart, and overcome this bug?

Charts fails when a function or ternary condition is added to the values to be plotted. Charts.

When a function is received as a value in the ForEach loop, the application crashes (Thread 1: signal SIGABRT), or if it is a ternary operator (condition ? true: false) it does not show the graph. The function should convert the value/attribute of the Core Data entity only if necessary, the data is stored in a common unit and depending on the display condition in an AppStorage variable it should be seen converted to another unit or displayed. This error occurs with any type of chart. It fails with both RulerMark and other charts like LineMark. The function works fine with Text and other similar views.

The Chart

	@AppStorage("unitView") var unitView: String = "Celsius"

   ...

			// CHART
			Chart {
				if statsByUser.takens > 1 {
					RuleMark(y: .value("AVG", getViewDegrees(statsByUser.avg, unitView)))
						.lineStyle(StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round, dash: [4, 6]))
						.foregroundStyle(.white.opacity(0.8))
				}

				ForEach(0..<temperatureByUserId.count, id:\.self) { item in

					LineMark(x: .value("Date", item + 1),
							 y: .value("Temperature", getViewDegrees(temperatureByUserId[item].degress, unitView)))
					.lineStyle(.init(lineWidth: 2, lineCap: .round, lineJoin: .round))
					.foregroundStyle(.white) //.mint [.pink, .purple, .mint]

				}
				.interpolationMethod(.cardinal)
			}
			// X-Axis
			.chartXScale(domain: 1 ... statsByUser.takens)
			.chartXAxis(.hidden)
			// Y-Axis
			.chartYScale(domain: statsByUser.min ... statsByUser.max)
			.chartYAxis {
				AxisMarks{ _ in
					AxisGridLine().foregroundStyle(.white)
					AxisValueLabel(centered: true).foregroundStyle(.white)
				}
			}
		}

The Functions

let unitDegress: [String] = ["Celsius", "Fahrenheit"]

func getViewDegrees(_ value: Double, _ unit: String) -> Double {
	var returnValue = value
	if unit == unitDegress[1] { // is Fahrenheit
		let t = Measurement(value: value, unit: UnitTemperature.celsius)
		returnValue = t.converted(to: .fahrenheit).value
	}
	return returnValue
}

Text works properly. Text("\(getViewDegrees(temperatureByUser.last, unitView), specifier: decimalSpecifier)")

Did you try to compute value first:

				ForEach(0..<temperatureByUserId.count, id:\.self) { item in
          let yValue = getViewDegrees(temperatureByUserId[item].degress
					LineMark(x: .value("Date", item + 1),
							 y: .value("Temperature", yValue, unitView)))

Ok, I've figured out what the problem is.

I've passed all the calculations back to the viewmodel, including the max, min and average. The value has been recalculated.

The problem is in the scale of the Y axis, and it keeps happening (if I remove it the problem disappears).

Everything works the first time, if I change the value from fahrenheit to celsius the error reappears (all the fields are recalculated perfectly), however, if I run the application again the information works correctly.

The bad thing is that Charts does not calculate automatically and with these values the scales look very bad.

** I changed everything from AppStorage to UserDefaults **

Chart

Chart {
				if statsByUser.takens > 1 {
					RuleMark(y: .value("AVG", statsByUser.avg))
						.lineStyle(StrokeStyle(lineWidth: 2, lineCap: .round, lineJoin: .round, dash: [4, 6]))
						.foregroundStyle(.white.opacity(0.8))
				}

				ForEach(0..<temperatureByUserId.count, id:\.self) { item in
					LineMark(x: .value("Date", item + 1),
							 y: .value("Temperature", temperatureByUserId[item].convertedDegrees))
					.lineStyle(.init(lineWidth: 2, lineCap: .round, lineJoin: .round))
					.foregroundStyle(.white) // [.pink, .purple, .mint]
				}
				.interpolationMethod(.cardinal)
			}
			// X-Axis
			.chartXScale(domain: 1 ... statsByUser.takens)
			.chartXAxis(.hidden)
			// Y-Axis
			.chartYScale(domain: statsByUser.min ... statsByUser.max)
			.chartYAxis {
				AxisMarks{ _ in
					AxisGridLine().foregroundStyle(.white)
					AxisValueLabel(centered: true).foregroundStyle(.white)
				}
			}

Model

func getMax(user: Int64) -> Double {
		let tempsUser: [Double] = self.tempeartures.filter{ $0.user == user }.map{ $0.degress }
		if tempsUser.isEmpty { return 0.0 }
		let maxValue = getViewDegrees(tempsUser.max() ?? 0, loadUnitDefault())
		return maxValue
	}

	func getMin(user: Int64) -> Double {
		let tempsUser: [Double] = self.tempeartures.filter{ $0.user == user }.map{ $0.degress }
		if tempsUser.isEmpty { return 0.0 }
		let minValue = getViewDegrees(tempsUser.min() ?? 0, loadUnitDefault())
		return minValue
	}

Without Scale Y Axis shows:

instead this:

How can I include a function (or calculation) in the values that Charts receives to draw the chart, and overcome this bug?
 
 
Q