I've found why SwiftUI doesn’t react to changes: it's because the hash for the distance value almost never changes:
// hash → distance
-7399245885813999995 → 13,37 m
-7399245885813999995 → 0,01337 km
-281655987593476708 → 1 337 cm
-7399245885813999995 → 13 370 mm
It seems like floating-point values (13.37, 0.01337 and 13370 -- which is stored as 13369.9999999) have their own hash, and integer values (1337) have another one.
Why is Measurement hashed this way, I don’t know. And as I can’t override the hash method, I'm bound to "box" Measurement into my own type:
struct MeasurementBox<UnitType>: Hashable where UnitType: Unit {
var raw: Measurement<UnitType>
func hash(into hasher: inout Hasher) {
hasher.combine(raw.value)
hasher.combine(raw.unit)
}
init(value: Double, unit: UnitType) {
self.raw = .init(value: value, unit: unit)
}
And this yields different hashes for different units:
3689241843365793539 → 13,37 m
-6289905827040915246 → 0,01337 km
5218327293601303449 → 1 337 cm
-237490459949056841 → 13 370 mm
This is, at best, a workaround, but at least it works.