Reminder: Swift still isn’t ABI-Stable!

Before we get this going, I’d just like to remind everyone that Swift is still not ABI stable. That means that binaries created with previous versions of Swift aren’t compiler-friendly with the current version. In plain English, this means that all of your files and dependencies have to be compiled with the same version of Swift; you cannot mix and match code written in different version of Swift.

Apple is trying to mitigate this by making Swift 3.0 the last version with (major) breaking changes (no promises). ABI stability is slated for Swift 4.

Should you upgrade to 2.3 or 3.0?

If you have a significant Swift code base — as we do here at VTS — the answer to this is:

yes, both.

If your Swift code base isn’t massive, then you should skip 2.3 and jump to 3.0.

Here are a few things to keep in mind:

Dependencies are important. Make sure to check if your dependencies support Swift 2.3 or Swift 3.0 — most major libraries/frameworks support both (Alamofire, Charts). However, something to keep in mind is that the upgrade to 3.0 is one way only. Since new development in Swift is going to take place in Swift 3.0, the 2.3 versions of all your dependencies are likely going to be frozen with no updates. Some version 8.x of Xcode will remove support for Swift 2.3. Swift 2.3 is intended to be an intermediate step for larger projects that will need a longer effort to upgrade to 3.0. If you have private CocoaPods that are shared across multiple projects, you will have to upgrade those first.

You can upgrade to 2.3, but you’ll be delaying the inevitable: You’ll still have to migrate to Swift 3 before the release of Xcode 9.

Migration Issues from Swift 2.2 to 2.3

The migrator might migrate Range<T> to CountableRange<T>. CountableRange<T> only exists in Swift 3.

The migrator will add the comment /*Migrator FIXME: Use a variable of type DispatchSpecificKey*/ to uses of dispatch_queue_set_specific(). This is only relevant for a future migration to Swift 3.

Migration Issues from 2.x to 3.0

Version 3.0 of Swift is the “break everything” release. Swift 3 is meant to break everything and get rid of anything that isn’t beneficial to the language long-term. That means a lot of things are going to change, and you’re going to have to change a lot of things to make your projects compliant.

Swift 2.3

Swift 2.3 is a very minor update. How minor? Effectively, there’s only one change: compile-time nullability checks of Objective-C code in updated Apple SDKs.

Other changes include some minor renaming and many optional initializers are now returning their intended object instead of optionals. This applies to things like instantiating nibs from a bundle.

Swift 3.0

Major Changes (things you may notice)

The definition of private has changed and the introduction of fileprivate

What was formerly private is now fileprivate. A fileprivate variable can be accessed within an extension. A private variable cannot be accessed within an extension to a class.

Learn more about this change

The definition of public has changed and the introduction of open

Currently, declaring a class or parameter public provides two capabilities:

It allows external modules to use the class/member. It allows external modules to override the class/member.

In Swift 3, public means externally usable, but not overridable. The previous functionality is encapsulated by open.

Learn more about this change

Verbs and nouns

Functions that end in -d are returning a new instance of that object.

This change applies to reverse and reversed, enumerate and enumerated, etc…

Objective-C booleans are now prepended with the word is and Foundation types no longer have the NS-prefix (where there is no conflict — for example, NSString still has the prefix, because it would otherwise conflict with String).

Foundation types now play nicely with Swift’s let and var declarations.

Learn more about this change

Import as member

Annotated C functions are imported as methods. The importer can usually infer these mappings automatically, and it means that using old C-APIs feels natural and native to Swift. Case and point, the CoreGraphics API. CoreGraphics had not been updated in this release (aside from annotations).

Read more about this change

Camel casing changes

UpperCamelCase has been replaced with lowerCamelCase in enumerations and properties that start with an acronym.

// Before

let red = UIColor.redColor().CGColor

// After

let red = UIColor.red.cgColor

(My least favorite change) Restructured condition clauses

You can no longer use the where keyword in guard, if, and while statements. The where keyword still applies to for loops in the form of for-in-where.

Also has some changes on the case clauses.

Learn more about this change

Consistent first argument labels

Pretty easy to understand this one: first parameter names are now required by default.

Learn more about this change.

(My favorite change) Handling implicitly unwrapped optionals

I think this change alone is worth the migration process if you have a shared-language project. So what is it?

Objective-C types that previously had properties of ImplicitlyUnwrappedType! now have the type WrappedType?. This applies everywhere except this case:

Learn more about this change

Better translation of Obj-C APIs

Naming has been made more clear.

Learn more about this change

Modernized dispatching

Learn more about this change

Collection Types have a new model.

Previously, when you wanted to traverse from one index to another in a collection type, you would use the successor method of the index. Now, that responsibility has been moved to the collection, such that now you write c.index(after: index). Collections may now have an index of any Comparable type.

(The following part only applies if you manually create Range objects. I don’t think any of us do)

As a side effect of this change, Range has been split into multiple types: Range, ClosedRange, CountableRange, and CountableClosedRange. ClosedRange now includes ranges that span the maximum value of a type (0…Int8.max). Range and ClosedRange are no longer iterable — they now only require a Comparable object as their bound (so you can create Range<String>).

Learn more about this change.

Objective C’s id is imported as Swift’s Any type

To quote Apple,

Since ‘id’ now imports as ‘Any’ rather than ‘AnyObject’, you may see errors where you were previously performing dynamic lookup on ‘AnyObject’.

Learn more about this change.

Small Changes (things you may not notice)

Optional comparison operators removed

Currently, nil-types are comparable. Case and point:

This makes it really easy to write bugs like this:

Now, you’re required to unwrap things before you compare them:

It’s one of those things that’s a really good idea but will likely demolish your unit tests.

Learn more about this change.

Closure parameter names and labels

A lot of closure parameter names have been renamed or made optional.

An example:

flatten renamed to joined

Learn more about this change.

Handling UnsafePointer<T>

The nullability of non-object pointer types is represented using optionals.

Learn more about this change.

Rounding floating point values is now the responsibility of the value.

Previously we would use the global C-functions floor and ceil to round a floating point type. These functions are still available but are being considered for deprecation.

Instead, we should now do the following:

There are additional rounding rules, such as:

toNearestOrAwayFromZero toNearestOrEven towardZero awayFromZero

Learn more about this change

Generic type aliases

Learn more about this change

Operator declaration syntax change

Learn more about this change

Objective C Constants are now Swift types

We are no longer using named strings for obj-c inter-op.

Learn more about this change

Stuff so small that you probably don’t care

NSError has improved bridging

Learn more about this change.

nulTerminatedUTF8CString renamed to utf8CString

Learn more about this change

Removal of repeating UnicodeScalar initializer of String

Learn more about this change

Failable UnicodeScalar initializers now return an optional.

Learn more about this change

No more tuple splatting

Learn more about this change

No more currying func declaration syntax.

Learn more about this change

Are these all the changes in Swift 3?

NO.

There are proposals still under review for this release. Several proposals have been deferred to 3.x, and I’ve also chosen to not include some additions and changes that I felt were very minor — like the removal or merger of some uncommonly used API calls.

In addition, I haven’t necessarily gone in depth with each of these individual changes, and have instead chosen to give a high-level overview of each change. Some changes have a bit of a ripple effect in their scope, and if you’re interested in the specifics of these changes you should really visit the Swift EVO project.

Changes under active review / awaiting review for this release

Changes deferred to a 3.x release

Bonus:

Things I’m sure we’re all glad were rejected: