Unit conversion is easy in Swift

Photo by Roman Mager / Unsplash

Foundation framework has many useful implementations, that can make our life easier. One of them is Unit and Measurement APIs.

Unit and Measurement

Measurment is a struct that holds the value of the given Unit. Additionally, it can convert, add, subtract, and do other arithmetical operations on this value. The best thing is, that it will do conversions for you!

UnitLength

One of the available types of Unit is UnitLength. It can represent any length value you can imagine, even famous from Star Wars - Parsec! How awesome is that?

We can use our length units to quickly create a unit converter calculator! For simplicity, we will just do a small exercise to convert some "EU" types to "US" types.

So how we can do that?

let lengthInCentimeters = Measurement(value: 100, unit: UnitLength.centimeters)
let lengthInFeet = lengthInCentimeters.converted(to: .feet)
print(lengthInFeet)
// prints 3.280839895013123 ft

And that's it! Since this API uses something called phantom types, we don't have to worry about conversion safety. .centimeters and .feet are both UnitLength. Additionally, all units have their own symbols, baked in! So you don't even have to worry about remembering symbols, at all!

Apple provides more than 20 dimensions, and every dimension defines most of the popular units, so you are covered with 99% of possibilities out of the box!

Custom units

What if there is something missing? Or do you want to create something "unusual"? No problem!

Liters per 100 Miles

Let's make a mix of "EU" fuel efficiency with "US" fuel efficiency - Liters per 100 Miles. Apple gives us dimension for fuel efficiency UnitFuelEfficiency.

We have to create a dimension, that is UnitFuelEfficiency:

extension UnitFuelEfficiency {
    static var litersPer100Miles: UnitFuelEfficiency {
        UnitFuelEfficiency(
            symbol: "l/100mi",
            converter: UnitConverterLinear(coefficient: 1/1.60934)
        )
    }
}

This couple of lines make it possible. The only thing that is really important is the converter. The converter is responsible for converting our new unit to the base unit of a given dimension, in our case is .litersPer100Kilometers.

Conversion

Let's use our new unit to convert fuel efficiency!

let litersPer100Kilometers = Measurement(value: 10, unit: UnitFuelEfficiency.litersPer100Kilometers)
let litersPer100Miles = litersPer100Kilometers.converted(to: .litersPer100Miles)
print(litersPer100Miles) // prints 16.0934 l/100mi
let mpg = litersPer100Miles.converted(to: .milesPerGallon)
let mpgFromliters = litersPer100Kilometers.converted(to: .milesPerGallon)
print(mpg) // prints 23.5215 mpg
print(mpgFromliters) // prints 23.5215 mpg

It works! Automatically it can convert to the base unit, but also it converts to other fuel efficiency units! How awesome is that! But what about arithmetics?

print(litersPer100Kilometers + litersPer100Miles) // prints 20.0 L/100km

Wow! Operators work for free, automatically converting between different units, and adding them properly!

I hope you like it and learn something!

Artur Gruchała

Artur Gruchała

I started learning iOS development when Swift was introduced. Since then I've tried Xamarin, Flutter, and React Native. Nothing is better than native code:)
Poland