Swift version: 3.0 | View all code snippets in this post on Github

Starting iOS 10 and macOS 10.12, Foundation supports units and measurments out of the box, in the form of (NS)Unit and (NS)Measurment respectively.

To get started, let’s import Foundation:

import Foundation

To define a measurment, a value and a unit are needed:

let snorlaxWeight = Measurement(value: 460, unit: UnitMass.kilograms)
// -> 460.0 kg

You can then effortlessly convert the measurment to another unit:

let snorlaxWightInImperial = snorlaxWeight.converted(to: .pounds)
// -> 1014.12723328454 lb

You can also define your own unit by extending one of the default dimensions available:

extension UnitMass {
  static let snorlax = UnitMass(symbol: "snorlax", converter: UnitConverterLinear(coefficient: 460))
}

The converter is used to transform the measurment from any given unit to the base unit of the dimension; Kilograms in the case of UnitMass. You can inspect the base unit of any dimension by calling baseUnit() on it.

UnitMass.baseUnit()
// -> kg

Once defined, your custom unit can be used alongside the pre-defined ones:

let statueOfLibertyMass = Measurement(value: 225_000, unit: UnitMass.kilograms)
let statueOfLibertyMassInSnorlax = statueOfLibertyMass.converted(to: .snorlax)
// -> 489.130434782609 snorlax

You can also define a custom dimension of units by subclassing Dimension if necessary. Here is an example that defines a new UnitDataRate class for measuring data transfer rates, often used in Internet speed tests:

class UnitDataRate: Dimension {
  static let kilobitPerSecond = UnitDataRate(symbol: "kbps", converter: UnitConverterLinear(coefficient: 1))
  static let megabitPerSecond = UnitDataRate(symbol: "Mbps", converter: UnitConverterLinear(coefficient: 1_000))
  static let gigabitPerSecond = UnitDataRate(symbol: "Gbps", converter: UnitConverterLinear(coefficient: 1_000_000))

  override class func baseUnit() -> UnitDataRate {
    return .megabitPerSecond
  }
}

let speed = Measurement(value: 100, unit: UnitDataRate.megabitPerSecond)
let speedInKpbs = speed.converted(to: .kilobitPerSecond)

// -> 100000 kbps

Learn More