Want to offer native, in-app customer service to your users? Get going quickly with Zendesk’s Mobile SDKs. Free with Zendesk.

Active Filters: Foundation


#277: MeasurementFormatter Basics 📐📏


Today we're going to continue our look at the new Measurement functionality in Foundation. (Bite #276). MeasurementFormatter offers some great ways to format and print Strings of our Measurements. Let's take a look.

First we'll make define some units to work with. One of the most common ones we'll use in our apps is Length (for example when displaying how "far away" something is).

let distance = Measurement(value: 1.4, unit: UnitLength.kilometers)

Next, we'll make a formatter:

let formatter = MeasurementFormatter()

We'll leave the locale setting alone, which causes it to use the current locale of the device. In our case, en_US.

Finally, we'll print the formatted String.

print(formatter.string(from: distance))

Nice. Now we can start to try out some of the options. Let's start with the *style, we have three choices:

formatter.unitStyle = .short // "0.87mi"

formatter.unitStyle = .medium // (the default) "0.87 mi"

formatter.unitStyle = .long // "0.87 miles"

We'll use the .long style.

By default, our device locale being en_US is causing the distance to formatted with "miles" instead of "kilometers" (our input value). We can change this with unitOptions:

formatter.unitOptions = [.providedUnit]

// "1.4 kilometers"

We can even drop down and configure the NumberFormatter (Bite #182) that the MeasurementFormatter uses when formatting the numerical part of our Measurements:

measurementFormatter.numberFormatter.maximumFractionDigits = 0

// "1 mi"

Last but not least, we can ask the formatter for a String representing only the name of some unit:

let formatter = MeasurementFormatter()
formatter.string(from: UnitLength.lightyears)

// "light yrs"


MeasurementFormatter is just another in a long list of wonderful little gems tucked away inside Foundation. Know of another that should be covered here? Send it along!.


#276: Measurement Basics 📏📐


Apple added something pretty neat to Foundation this year: Measurements. We can represent units, convert them to other units, compare them, and even convert them into formatted strings. Let's dive in.

It all starts with a Measurement.

let fuel = Measurement(value: 184, unit: UnitVolume.liters)

There are tons of different categories of units such as Volume, Mass, Speed, Power, Length, and many more.

Once created, a Measurement can be converted into any of other units in its category:

print(fuel.converted(to: .gallons))
// "8.18933748259766 gal"

We can also perform mathematical operations and comparisons on Measurements:

let tripLegA = Measurement(value: 1.4, unit: UnitLength.lightyears)
let tripLegB = Measurement(value: 2.3, unit: UnitLength.lightyears)

let tripTotal = tripLegA + tripLegB

print(tripTotal) // "3.7 ly"
print(tripLegA > tripLegB) // "false"

Last but certainly not least, we can nicely format a measurement into a String. Apple provides a MeasurementFormatter type that is fully locale-aware. This allows us to easily display Measurements in our apps in whichever ways our users expect.

let formatter = MeasurementFormatter()
formatter.locale = Locale(identifier: "en_US")
formatter.string(from: tripTotal)

// "21,751,587,607,342.14 mi"

formatter.locale = Locale(identifier: "fr")
formatter.string(from: tripTotal)

// "35 005 700 000 000 km"

Foundation is such a powerhouse of functionality, it can be easy to miss great new additions like this. Next time, we'll learn more about formatting Measurements for display in our apps.

Attributed Strings are a fantastic way to work with rich, styled-text. (We've covered them in Bites #143 & #144 for the curious.) We've even looked at ways to improve upon how verbose the Foundation NSAttributedString API can be.

Today we'll check out another approach using a library from Eddie Kaiger called SwiftyAttributes. It dramatically improves how we work with Attributed Strings. Let's dive in.

Let's start by looking at how things work in vanilla Foundation:

let attributes: [String: AnyObject] = [
  NSFontAttributeName: UIFont(name: "AvenirNext", size: 16.0)!,
  NSUnderlineStyleAttributeName: NSNumber(value: NSUnderlineStyle.styleSingle.rawValue),
  NSForegroundColorAttributeName: UIColor.gray

let someString = NSAttributedString(string: "Hello World", attributes: attributes) 

The functionality is wonderful, but even in fairly standard usage thie code can prove a bit difficult to parse at a glance.

Now, let's create the same string, but let's use SwiftyAttributes's API:

let someString = "Hello World"
  .withFont(UIFont(name: "AvenirNext", size: 16.0)!)


Things get even nicer when we need to concatenate two NSAttributedStrings together. We've all had to do this before and it could have involved applying attributes to specific ranges, etc. Now, we can use a much more declarative and readable syntax:

let someString = "We can easily ".withFont(.systemFont(ofSize: 16)) +
                   .withFont(.systemFont(ofSize: 16))
                   .withUnderlineStyle(.styleSingle) +
                 " certain words.".withFont(.systemFont(ofSize: 16))

Under the hood, SwiftyAttributes takes a pragmatic approach by extending both Swift's String type as well as NSAttributedString with a fairly comprehensive set of delicious, sugary functions:

func withFont(_ font: UIFont)
func withParagraphStyle(_ style: NSParagraphStyle)
func withTextColor(_ color: UIColor)
func withBackgroundColor(_ color: UIColor)
func withLigatures(_ ligatures: Ligatures)
func withKern(_ kernValue: Double)
func withStrikethroughStyle(_ style: NSUnderlineStyle)
func withUnderlineStyle(_ style: NSUnderlineStyle)
func withStrokeColor(_ color: UIColor)
func withStrokeWidth(_ width: Double)
func withShadow(_ shadow: NSShadow)
func withTextEffect(_ effect: String)
func withAttachment(_ attachment: NSTextAttachment)
func withLink(_ link: URL)
func withBaselineOffset(_ offset: Double)
func withUnderlineColor(_ color: UIColor)
func withStrikethroughColor(_ color: UIColor)
func withObliqueness(_ obliquenessValue: Double)
func withExpansion(_ expansion: Double)
func withWritingDirections(_ directions: [WritingDirection])

This allows us to get creative with how we mix and match the two types:

let someAttributedString = fromSomewhereElse()

let someString = someAttributedString + "\n\nNeat!".withTextColor(.brown)

Learn more about SwiftyAttributes at git.io/swiftyattributes

Today we'll look at a new library from Krzysztof Zabłocki called KZFileWatchers. It allows us to easily monitor local and remote files, running code when changes occur. Let's dive in.

Watching files for changes is a common technique used when creating "live" updating interfaces.

This is a popular technique among web developers. For example, it's now common to use a tool to "live reload" a web page whenever a CSS file is changed.

Live updating techniques can dramatically change how we work, allowing us to try out changes more rapidly.

KZFileWatchers helps us build this type of functionality by providing two simple tools:

FileWatcher.Local is for observing local file changes. (It can even cross sandbox boundaries for debug simulator builds, think "config files on the desktop").

FileWatcher.Remote is for observe remote file changes. We can place a file on a server somewhere, and KZFileWatchers will use the Etag headers and Last-Modified-Date. This even works with Dropbox. Neat.

Let's use a FileWatcher.Local to make a live updating label.

First we'll create a label:

let textLabel = UILabel()

Then we'll create our file if it doesn't already exist:

let filename = "label-content.txt"
let middle = FileWatcher.Local.simulatorOwnerUsername()
let path = "/Users/\(middle)/Desktop/\(filename)"

if FileManager.default.fileExists(atPath: path) == false {
  try! "Hello, world."
    .data(using: String.Encoding.utf8)?
    .write(to: NSURL.fileURL(withPath: path))

Finally, we'll wire up a watcher to our file's path, and update our label when the file changes:

let watcher = FileWatcher.Local(path: path)

try! watcher?.start {
  switch $0 {
  case .updated(let data):
    textLabel.text = String(
      data: data,
      encoding: String.Encoding.utf8
  default: break

We can use this technique to drive all sorts of systems. With this we can easily enable/disable features, change content of labels in our UI, or build a full fledged theming system that updates in "real time".

More info about KZFileWatchers can be found at git.io/filewatchers

We've covered GCD a few times back in Bites #85 & #35. This year, GCD is getting a huge overhaul that brings it into the modern world of Swift. Today we'll take a look at what's changed, let's dive in.

TLDR: Grand Central Dispatch now has a richly typed Swift 3 API.

Here's a basic usage example:

let queue = DispatchQueue(label: "com.jakemarsh.image-processing")

queue.async {
  let thumbnail = image.resize(to: thumbnailSize(for: image))

  DispatchQueue.main.async { imageView.image = thumbnail }

Here we create a new queue, and enqueue some image processing work on it. Then, we do the same thing, but back on the main queue, enqueueing the work of setting resized image on our imageView there.

That's just the beginning. Here's a few more examples of how to use the new "swifty" GCD:

Time & Delay:

let delayTime = DispatchTime.now() + .seconds(1)

DispatchQueue.main.after(when: delayTime) {

For seasoned GCD users, it may take some getting used to, but the new API is much safer and more intuitive to use in Swift. Neat!

Markdown is awesome. For those not familiar, read up on why Markdown is awesome in this fantastic post by Brett Terpstra.

When it comes to using Markdown on iOS and OS X, there's tons of options. Today we'll look at one popular solution from Simon Fairbairn called SwiftyMarkdown. It helps us translate Swift Strings containing Markdown into NSAttributedStrings. Let's take a look.

let md = SwiftyMarkdown(string: "# SwiftyMarkdown\nConverts *Markdown* files and strings into NSAttributedString")

It's that simple! SwiftyMarkdown will use some defaults for fonts, colors, etc. Customizing those is quite simple:

md.body.fontName = "AvenirNextCondensed-Medium"

md.h1.color = UIColor.redColor()
md.h1.fontName = "AvenirNextCondensed-Bold"

md.italic.color = UIColor.blueColor()

We can supply custom colors and fonts for each different tag, SwiftyMarkdown even supports inline links, neat!

More info about SwiftyMarkdown can be found at git.io/swiftymarkdown

Often when working with data from an API or third-party we'll need to manipulate or analyze it in a very specific way. In these cases, many of us simply search Google for "how to do the thing to a String in Swift". This usually works out fine, but what a bummer.

Today we'll check out a library from Andrew Mayne called SwiftString, which can help us here.

SwiftString is essentially a collection of a ton of String manipulation and analysis utilities. It has functions like this:

"<rock>blah</hardplace>".between("<rock>", "</hardplace>") // "blah"
"hello".isNumeric() // false
"hello7".isNumeric() // false
"31.0".isNumeric() // true
"-31.0".isNumeric() // true
"star wars".split(" ")[0] // "star"
"star wars"[0...1] // "st"
"#203: Simplifying Common String Operations".slugify() // "203-simplifying-common-string-operations"
"Some [string], *with* %junk in it.)".stripPunctuation() // "Some string with junk in it"
"yay &quot;strings&quot;".decodeHTML() // "yay \"strings\""

We might only need one or two of these functions in a single app, but thanks to SwiftString, we'll never have to write them ourselves again.

More info about SwiftString can be found at git.io/swiftstring

Today we'll follow up with another Bite in our localization series (sort of). Units of measurement are important to get right when localizing our apps for different cultures.

Today we'll look at a library from Khoa Pham called Scale that can help us convert between different units of measurement (for either localization or just-for-fun purposes). Let's begin.

Scale makes it incredible simple to work with different units of measurement:

let length = 5.kilometer + 7.meter  // 5,007 meters
let weight = 10.0.kilogram * 5.gram // 50,000 grams

Everything is strongly-typed, and conversion is a breeze:

2.week.to(unit: .hour) // 336 hours

Scale even provides nicely formatted debug output. For example, print'ing that last statement logs:

Time(value: 336.0, unit: Scale.TimeUnit.hour)

Scale supports a wide variety of units:

let angle = 5.degree + 2.radian
let area = 5.acre + 2.hectare
let metric = 5.base + 2.kilo
let volume = 5.liter + 2.gallon
// + many more...

One more example to show off how readable Scale's API is. Here we'll add two typed units together, then convert them:

let time = 4.day + 1.week
print(time.to(unit: .week))
Time(value: 1.57142857142857, unit: Scale.TimeUnit.week)

More info about Scale can be found at git.io/scale

.stringsdict files were added in iOS 7 and OS X 10.9. They allow us to "pluralize" text in our app without a bunch of switch or if statements.

let spaceships = [Spaceship(selected: true)]

let pluralized = String.localizedStringWithFormat(
  NSLocalizedString("%d ships selected",
    comment: "how many ships selected"),
  spaceships.filter { $0.selected }.count

The localizedStringWithFormat function is terribly smart.

It will look for a Localizable.stringsdict file before returning and query it for the correct format string to use before returning our final formatted string.

A Localizable.stringsdict is really just a .plist file with a few special strings in it.

We can create a Localizable.stringsdict file either completely by hand in a text editor, or by adding a new Property List to our project and naming it Localizable.stringsdict.

Now that we have a .stringsdict file, let's use it.

The root key is the same one we passed into NSLocalizedString.

Then, we define a sort of string-replacement-variable using some special characters: %#@VARIABLE_NAME_HERE@. The system will then find the sub-dictionary that shares a name with this variable, and use it to pluralize.

We can provide cases for zero, one, two, few, many, and other. Each potential plural case is optional for each language, except other.

Download an example project showing off this functionality here.

Hat tip to Matthew Bischoff for the idea for today's Bite, which actually inspired a whole series of localization Bites with more still to come!

Today we'll continue our series on localizing our apps by looking at NSNumberFormatter.

It can help us make sure we're displaying numbers using the format a user expects in their culture or language, as well as display numbers in some fun ways. Let's get started.

First, let's see how we can take advantage of NSNumberFormatter when localizing our app.

We'll create a new formatter, and tell it to use the user's current locale. (An NSLocale is a class that encapsulates information about linguistic, cultural, and technological conventions and standards).

let formatter = NSNumberFormatter()
formatter.locale = NSLocale.currentLocale()

Now, we can set what kind of format we'd like to perform. NSNumberFormatter has a ton of great built-in styles. Let's try the Currency style:

formatter.numberStyle = .CurrencyStyle
formatter.stringFromNumber(2187.31) // "$2,187.31"

Then, we ask the formatter for a string from a number.

Apple has done all the hard work of figuring out how numbers should change when displayed in different locales. The example before showed the output from a device in the US, what about one from Germany? Let's try it:

formatter.locale = NSLocale(localeIdentifier: "de_DE")
formatter.numberStyle = .CurrencyStyle
formatter.stringFromNumber(2187.31) // "2.187,31 €"

Neat! What else can NSNumberFormatter do? Here's some fun examples:

formatter.numberStyle = .SpellOutStyle
formatter.stringFromNumber(21) // "twenty-one”
formatter.numberStyle = .OrdinalStyle
formatter.stringFromNumber(21) // "21st"

In addition to all of that, NSNumberFormatter also has an insanely long list of customizable properties allowing us to create completely custom formatters (best done via subclassing).

Page 1 of 3