One of the really great utilities within Foundation is the Unit and Dimension types which facilitates all sorts of conversions.
Especially useful was the ability to convert between various unit types. For example, feet and inches, gallons and litres, etc.
The documentation recommends the following pattern to extend a Unit with additional Dimensions:
Creating a Custom Dimension Subclass
You can create a new subclass of
Dimension
to describe a new unit dimension.For example, the Foundation framework doesn’t define any units for radioactivity. Radioactivity is the process by which the nucleus of an atom emits radiation. The SI unit of measure for radioactivity is the becquerel (Bq), which is the quantity of radioactive material in which one nucleus decays per second (1 Bq = 1 s-1). Radioactivity is also commonly described in terms of curies (Ci), a unit defined relative to the decay of one gram of the radium-226 isotope (1 Ci = 3.7 × 1010 Bq).
You can implement a
CustomUnitRadioactivity
class that defines both units of radioactivity as follows:
class CustomRadioactivityUnit: Dimension {
static let becquerel = CustomRadioactivityUnit(symbol: "Bq", UnitConverterLinear(coefficient: 1.0))
static let curie = CustomRadioactivityUnit(symbol: "Ci", UnitConverterLinear(coefficient: 3.7e10))
static let baseUnit = self.becquerel
}
In usage, this would end up looking something like:
let measurement = Measurement(value: 100, unit: CustomRadioactivityUnit.curie)
let converted = measurement.converted(to: CustomRadioactivityUnit.becquerel)
And prior to Swift 6, this worked very well. However, as Dimension isn't Sendable, the pattern suggested in the documentation no longer compiles. The only workaround I've come up with is to turn the static members into computed vars, like so:
class CustomRadioactivityUnit: Dimension {
static var becquerel: CustomRadioactivityUnit {
CustomRadioactivityUnit(symbol: "Bq", UnitConverterLinear(coefficient: 1.0))
}
static var curie: CustomRadioactivityUnit {
CustomRadioactivityUnit(symbol: "Ci", UnitConverterLinear(coefficient: 3.7e10))
}
static var baseUnit: CustomRadioactivityUnit { curie }
}
But of course, this adds a substantial amount of allocation overhead, which should probably be avoided.
I'm assuming the train has left the station on making this type Sendable, so are there any plans to create a Swift 6 equivalent of this API instead?