Swift 5 is released!

March 26, 2019

Swift 5 was released yesterday, and swift developers have been patiently (or not) waiting for this release for quite some time. One of the biggest new features is a stable ABI.

Stable ABI

For developers, a stable ABI (application binary interface) means that in the future, the swift runtime modules will not need to be included in each app's package. Until now, every swift app bundled a separate copy the swift runtime inside it's own package. So app filesizes were artificially inflated and there were potentially many, many copies of the swift runtime somewhere on every user's device. The upside to this arrangement is that apps need not worry what version of swift the user could support, since they BYOS'ed (bring-you-own-swift) their own runtime.

Now that the swift ABI is stable, apps can count on the fact that no matter what version of swift is installed on a user's device, the app can use that version to run itself.

What do you mean ABI?

If you understand what an API (application programming interface) is, you already understand what an ABI is, at least on some level. APIs define the set of knobs, levers, and switches that are exposed from a particular library, framework, or code base. The API defines how you use and interact with code.

Wait, what do you mean 'API??'

Let's say you have a particular library that lets you deal with Widget objects, and there exists some API for working with these objects. Maybe the library gives you a few functions, like these:

func transmogrify(widget: Widget) -> Widget
func confabulate(widget: Widget)
func computeInertialMass(ofWidget: Widget) -> Double

When using and calling these functions, you don't care how the library does all this stuff. You only care that it does it for you. The author of the library is free to change the inner workings of the library as long as they still provide you with the same sets of switches, knobs, and levers (i.e. those three functions). If, for some reason, the library author removes a lever, or even just rearranges the existing levers, suddenly the knowledge you have of how to use the library has vanished. The code you wrote that uses this library stops working, and you must now figure out what's changed so you can update your own program.

If you understand the consequences of not being able to rely upon a particular API, then you understand why changes in the ABI are equally problematic. The ABI analogous to a "compiled API". It's the set of conventions that determine how a binary is laid out and how to interact with it. Changes in the ABI may mean that the order of arguments in a function change, or perhaps the way serialized data is saved in an internal type. Either way, it means that we no longer know for certain that we can find what we want and where we want it in a particular binary.

Other New Stuff

Raw Strings

Swift now supports raw strings, which ignore any characters or symbols that might otherwise have been interpreted as significant (like control characters, terminators, etc). To make a raw string, just surround it by and equal number of # symbols like this:
let rawString = #"What's this "widget stuff" \Widget.weight mean?"#

In the above example, the " marks don't end the string, nor does the \ print out the Widget's keypath. In fact, the way you normally print values inside a string "like this \(num)" will also be interpreted as a string. So you'll have to escape your string with a # to have your string printed, like this:

let num = 7
let str = #"My favorite number is \#(num)"#

You can use any number of symmetrical # symbols to escape your strings. This is particularly useful when your string has a # in it.

let str = ###"Twitter has lots of #hastags."###

isMultiple

Now, BinaryInteger has the isMultiple(of:) method for determining whether a number is a multiple of some other number. This is a more expressive way of writing code when you would otherwise be using the remainder % operator.
let x = 16
x.isMultiple(of: 2) //true

NOTE: that the % operator in swift is not the modulo operator, but rather remainder. They are similar, but different, primarily when it comes to how they handle negative numbers.

Result Type

public enum Result {
    case success(Success), failure(Failure)
}

Swift 5 has baked in functionality that many developers have been asking for when it comes to dealing with success and failure, particulary in an asychronous context. We now have the Result class which lets us encapsulate either the successful completion of some asynchronous call (and its resulting value 🤓) or gives us the error that occurred when the asychronous call failed for some reason. Using Result looks like this:

downloadHugeFile(from: "jeffmcclay.com/photo") { result in
	switch result {
	case .success(let file):
		myImageView.image = file
	case .failture(let error):
		print(error.description)
	}
}

The Rest

There's lots of other improvements like improvements to dictionary and swift support for SIMD vectors so be sure to check those out. See all the details at swift.org.

Grand Canyon Snow

Grand Canyon, AZ | 2016

The Dells

Prescott, AZ | April 2012

Flying

Prescott, AZ | November 2010

High Quality | Low Quality

ERAU Skydiving

Prescott, AZ | September 2010

High Quality | Low Quality

New Zealand BASE

South Island, NZ | May 2009

New Zealand

April 2009

Crack Attack

March 2009 → Indian Creek, Utah

Utah Climbing

October 2008 → Moab/Indian Creek, Utah

Monument Valley Sunset

October 2008 → Utah

The Dells

October 2008 → Prescott, AZ

Heaven/Hell

August 2008 → CA

Hot Air Balloon Jump

May 2008 → Perris, CA

Eloy - April

April 2008 → Eloy, AZ

Woodson

March 2008 → Mt Woodson, CA

Eloy

May 2008 → Eloy, AZ

VIDEO

Triton Tower

December, 2007 → El Cap Wall

Skydiving

September 2007 → Perris, CA

Tahquitz

August 2007 → Idllywild, CA

Leonids, 5.9+

December, 2007 → El Cap Wall

Treasure Lakes

July, 2007 → Eastern Sierra, CA

La Jolla Shores

July, 2007 → La Jolla, CA

Photographs

May, 2007