Assumed audience: people interested in the Swift programming language.
Starting iOS 10 and macOS 10.12, Foundation supports units and measurements out of the box, in the form of (NS)Unit and (NS)Measurement respectively. Let’s take a look at how they work.
Note: All code snippets below are written in Swift 3.0.
To get started, let’s define a measurement. To do that, you have to pass a value and a unit to the initializer:
import Foundation
let snorlaxWeight = Measurement(value: 460, unit: UnitMass.kilograms)
// -> 460.0 kg
You can then effortlessly convert the measurement 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 measurement 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
- WWDC session 238
- Measurements and Units in Foundation by Ole Begemann.
- iOS 10: Measurements & Units Screencast by Sam Davies.
Found any typos? Edit the post here.