HKQuantity and HKUnit support all of the common units of measurement, SI and otherwise, such as gram()
, pound()
, and stone()
.
The HealthKit classes also support custom complex units such as "foot-pound", "meters-per-second", or "meters-per-second-squared" via unitMultiplied(by:)
, unitDivided(by:)
, and unitRaised(toPower:)
The unit class supports most standard SI units (meters, seconds, and grams), SI units with prefixes (centimeters, milliseconds and kilograms) and equivalent non-SI units (feet, minutes, and pounds). HealthKit also supports creating complex units by mathematically combining existing units.
Does HealthKit, though, support completely custom units of measurement to model simple non-complex measurements like mass, length, or volume?
Imagine an MIT student project for a bridge-walking pedometer app. The app would certainly need to calculate and display distances in Smoot units.
let smoot = HKQuantity(unit: .meter(), doubleValue: 1.7018)
let meter = HKQuantity(unit: .smoot(), doubleValue: 1)
extension HKUnit {
class func smoot() -> Self {
// ???
}
}
How can a smoot()
be modeled in HealthKit HKUnits
?
2
Answers
HealthKit does not currently seem to support custom
HKUnit
s when creatingHKQuantity
s. You are limited to the customHKUnit
class functions Apple provides, such as.gram()
and.cupImperial()
.HKQuantity
does, though, provide a first-class unit converter. You can input and output values in any unit that Apple provides.This allows us to write an
HKCustomUnit
layer on top of the existing HealthKit units with no need to pull in the Measurement API from Foundation:With the extension function names based on the existing
HKQuantity
API, usingHKCustomUnit
is identical to using the providedHKUnit
:The point of HealthKit sharing is to allow different apps to be able to contribute and make use of health data. For this to work, the data recorded in the HealthKit store needs to be in common units.
If you were to record a distance in Smoots then that would meaningless to any other app that read the data.
Displaying data in your app is a different story. You can define your own
UnitLength
for Smoot and use that to convert Meters to Smoots for display or convert entered Smoots to Meters for storage:This gives the output:
The short answer is you can’t store custom units in HealthKit, but you don’t need to – You handle them with input/output, not storage.
You cannot create your own
HKUnit
– From the documentationUsing the
UnitLength
extension above you could create some convenience functions to convert to and fromHKQuantity
for you