New approach to formatters in iOS 15

There are huge foundation news regarding formatters. They were basically moved behind the scenes.

iOS comes with many useful formatters that help us present data in localized format without having to do it ourselves. The traditional workflow is that we first instantiate the formatter (preferably with reusability in mind), configure it and then use it to format data.

This is no longer case in iOS 15 (as well as macOS 12, watchOS 8 and other current OSes). Instead these formatters are hidden behind new API that starts with formatted method.

The idea is that on any "thing" like a Date, number and similar, you can call formatted and optionally customize it to your liking. It will probably take some getting used to, but we won't have to deal with managing formatters ourselves.

Formatting dates with iOS 15

Let's start with some Date examples. Feel free to follow with Xcode 13 Playground 🚀

let now = Date()
print(now.formatted())
// 6/8/2021, 8:00 PM

print(now.formatted(date: .complete, time: .omitted))
// Tuesday, June 8, 2021

Need the ISO8601 for an API? No problem.

let now = Date()
print(now.formatted(.iso8601.dateSeparator(.dash)))
// 2021-06-08T181205Z

Some of the things will probably take a bit longer to get used to.

let now = Date()
print(now.formatted(.dateTime.year().month()))
// Jun 2021

print(now.formatted(.dateTime.year(.twoDigits).month(.wide)))
// June 21

The .dateTime variant gives you more options to build exactly the date you want. This also lets us specify custom locale:

let now = Date()
print(now.formatted(.dateTime.locale(Locale(identifier: "cs"))))
// 8. 6. 2021 20:13

Formatting numbers

We can use similar approach to format various numbers.

print(40.formatted(.percent))
// 40%

print(40.formatted(.currency(code: "eur")))
// €40.00

print(0.2948485.formatted(.number.precision(.significantDigits(2))))
// 0.29

There is just a ton of options. Unfortunately the autocomplete for these doesn't work that great yet.

Similarly we can use the ByteCountFormatter to format file sizes.

print(38436483.formatted(.byteCount(style: .file, allowedUnits: .all, spellsOutZero: true, includesExactByteCount: false)))
// 38.4 MB

This shows all the available options.

Formatting with ListFormatter

ListFormatter is also represented by the formatted method. It is available on collections:

let appleStuff = ["iPhone", "iPad", "Mac"]
print(appleStuff.formatted())
// iPhone, iPad, and Mac

There are of course much more options available, my goal was to mainly demonstrate the new approach formatting dates, numbers and more in new versions of Apple's operating systems.

Source: What's new in Foundation

Uses: Xcode 13 & Swift 5.5

Filip Němeček profile photo

WRITTEN BY

Filip Němeček @nemecek_f

iOS blogger and developer with interest in Python/Django. Telling other devs' stories with iOS Chat.