Swift 3: What's Changed?

Written by: Reinder de Vries, September 18 2016, in App Development

Swift 3.0 is the first major iteration of the Swift programming language that’s open source. Since it’s latest inception in March 2016, Swift contributors have made major improvements to the language. So what’s changed?

Note: If you’re learning how to code Swift, don’t worry too much about these language changes. It’s not like everything breaks, or becomes irrelevant. Just make sure to use an up-to-date course or book, and check out articles like this one!

In this article you’ll learn:

  • The most important changes in Swift 3
  • How to upgrade your code
  • How to understand programming language changes

You can group the changes for Swift into two categories:

  • Everything that was already “deprecated” in Swift 2.2, like the ++ operator
  • Refinements and modernisations of the Swift language, making it more “swifty”

Note: Deprecated, or deprecation is simply marking a language keyword or feature for deletion.

It’s like the Swift language designers tell all programmers: we’re going to remove this keyword, or this syntax, or this feature, in the next iteration of Swift. This gives programmers time to change their code, but also ensures that older apps don’t immediately break with a new iOS or Swift release. (Read more on ABI Compatibility, here.)

Swift 2.2 to 3.0

Thanks to the Swift Evolution repository on GitHub we can all see what’s happening inside the Swift language. Some of us even actively contribute to the development of Swift!

Swift 2.2, released in March 2016, had a lot of improvements that are made definitive in Swift 3.0.

–, ++ are now += 1 and -= 1

You’re familiar with the increment operator ++, like this:

var i = 42
// i is now 43

This operator is removed in Swift 3, and replaced with its cousin +=:

var i = 314
i += 1
// i is now 315

Also, C-style for-loops are removed from the language. The code sample below, of such a for-loop, isn’t valid anymore:

for var i = 0 ; i < 10 ; i++ {

(It’s called “C-style” because this method of writing for-loops is copied from programming language C.)

Instead, Swift uses it’s own version of a very concise and readable set of for-loops:

for index in 0..<10

(Note that the range operator 0...10 is inclusive of 10, and 0..<10 is not – like i < 10.)

The reasons for these improvements aren’t just of a purist nature, they also make the Swift language more readable and less prone to errors.

The contributor who suggested this change in the Swift language, Erica Sadun, noted that the for-in loop style is much more succinct and versatile (you can also use it for looping over arrays) than its C-style counterpart.

Label ALL The Arguments!

For long Swift (and Objective-C) methods have included the first parameter label in the method name, like this:


The first agument "Ford" doesn’t need a label, but next arguments always require a label:

launchRocketWithVelocity(10000, toPlanet: "Mars")

See that withVelocity part there, part of the method name? That is the first argument’s label in Swift 3:

launchRocket(withVelocity: 10000, toPlanet: "Mars")

That makes it much clearer! Likewise, the Swift 2.2 search method indexOf(_:) is index(of:) in Swift 3:

hitchhikers.index(of: "Ford")

I’ve always found it confusing that the first argument had no label, and next arguments did. Back in the Objective-C era, this language feature always lead to endless function and method names like stringByReplacingStringWithOccurrencesOfFrappuccino:

(Confused by “arguments” and “parameters”? A parameter is like a parking spot, and the argument is the car you park in it. It’s OK if you call everything a parameter – it’s all input for a function, anyway.)

Swift Rules Objective-C

Swift has become more defined and strict in it’s views of language syntax. You can imagine that, when Swift changes, Objective-C doesn’t necessarily change with it. You do use Objective-C, often unknowingly, in your code however! UIKit, the library that powers stuff like table views and buttons, is written in Objective-C.

Swift 3, in many cases, overrides the language conventions of Objective-C. This means that, when you work with Objective-C frameworks in your Swift code, you need to use the new Swift conventions, and vice-versa, the Objective-C code that calls your Swift code needs to follow these conventions too.

An example:

override func viewWillAppear(animated: Bool)
    // Do stuff

You use this Swift function in your code when you want to override the behaviour of a view controller, when it’s about to appear, like updating what’s on screen. This function, which is part of your Swift code, will be called from Objective-C because it’s part of UIKit.

Given the new convention of always naming the first parameter, the example above now becomes this:

override func viewWillAppear(_ animated: Bool)
    // Do stuff

See that underscore _? This indicates the first parameter is unnamed. Confusing? YES!

Look at it like this:

  • Swift’s rules go before Objective-C’s rules
  • Swift says: name all parameters
  • Objective-C says: OK, I can’t do that, because I don’t change like you do
  • Swift says: OK, then I will explicitly use an unnamed first parameter

It’s like the tables have turned, really. What was once default, now has to be made explicit. Thanks to this change, however, all other Swift code becomes much clearer and easier to use.

All Function Parameters Are Constants

OK, check out this Swift 2.2 function:

func sayHello(name:String, var greeting:String)
    // if time is > 12:00
    greeting = "Good Afternoon"

    print("\(greeting), \(name)")

As you can see, this function prints out a response based on a name and greeting parameter. In the afternoon, it automatically greets you with “Good Afternoon.”

Note the var for the function parameter greeting? It’s a hack: this way you can declare a parameter as a variable instead of as a constant. This means it’s easier to change the parameter in the function body.

As of Swift 3, you can’t do that anymore, because all function parameters are constants. There is no way you can change a constant – that’s the point!

Instead, you’d do this, using a temporary variable:

func sayHello(name:String, greeting:String)
    var changedGreeting = greeting

    // if time is > 12:00
    changedGreeting = "Good Afternoon"

    print("\(changedGreeting), \(name)")

Clearer Selectors + Auto-Completion

Selectors always weird me out for a bit. The “things” your code can do have many names:

  • Functions
  • Methods
  • Selectors
  • Actions

Although each of these are slightly different from one another, it’s still confusing. Swift 3 removes part of that confusion by making selectors more like functions.

Take this from Swift 2.2, for instance:

NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("onDataReceived:"), name: "dataReceived", object: nil);

You connect a method from your code to a notification that’s posted in the default Notification Center, effectively calling that onDataReceived: method when the event is posted.

Notice that colon in onDataReceived:? I always forget it! It’s a notation for the first (unnamed) parameter of the method. The selector is written as a string, so there’s no compile-time checking going on – because I forget the colon, my app will crash.

Fortunately, Swift 3 has a solution: don’t use strings with selectors. The code example changes to this:

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(onDataReceived(notification:)), name: "dataReceived", object: nil);

See what changed? This: #selector(onDataReceived(notification:))

  • Note the #selector keyword
  • Note the double wrapping, one () for the #selector keyword, and one () for the function itself

Note a very important difference, too. Swift 2.2 used unnamed first parameters, but as you now know, Swift 3 requires you to name all parameters. This means that if method onDataReceived has one parameter called notification, you’ll need to specify that in the function signature.

Don’t worry about writing those function signatures right, though. Xcode 8 has terrific auto-completion, so hit the Escape-button when you’ve typed #selector( and you can select your function from a list!


Remember NeXTSTEP? It’s one of those early-Apple trivia…

When Steve Jobs returned to Apple in 1997 he took with him the NeXTSTEP OS. Without knowing it, all of us iOS coders still work with the remnants of that operating system: the NS prefix for many Cocoa Touch classes is a reference to NeXTSTEP!

In Swift 3, many of the basic classes will drop the NS prefix, making that trivia even more obscure. (This is one for coder meetups. Show your Swift supremacy by unemphatically droning about Swift obscurities… HA!)

Notable basic classes are:

  • NSTimer will now be Timer
  • NSUserDefaults will now be UserDefaults
  • NSBundle will now be Bundle
  • NSFormatter will now be Formatter

“Omit Needless Words” Irony?

Perhaps you’ve checked out Objective-C. Did you notice how ridiculously lengthy some methods and functions are? It went something like this…

[object stringWithStringByAppendingStringWithAnotherStringByReplacingStringsWithCharacters:characters bySignalingTheMothership:mothership atTimeByReplacingTimeWithFrappuccino:frappucino whileEngagingTheBistroDrive:bistroDrive]

The most significant change in Swift 3 had a surprising small amount of words: omit needless words.

Swift uses Objective-C code, because many Cocoa Touch libraries are written in Objective-C, so it’s automatically riddled with all those lengthy method names. This makes your code unnecessarily long and complicated. Most importantly, some of these method names include needless words, like this one:

var quiGon = "Your focus determines your reality"
quiGon.stringByReplacingOccurrencesOfString("focus", withString: "yakitori")

In Swift 3 this will be:

var quiGon = "Your focus determines your reality"
quiGon.replacingOccurrences(of: "focus", with: "yakitori")

Notice this:

  • All needless occurences of the word “string” are removed. It’s kinda obvious you’ll replace a string with a string, returning a string, right?
  • The first parameter is named, denoting what string will be replaced
  • The method name includes “replacing”, which will use in-place changing of the variable – more on this later

Ermagherd Kood Nurmel English >.<

Swift 3 will read more like a normal language. We’re instructing a computer, after all!

Check out this array:

var names = ["Ford", "Arthur", "Zaphod"]

Let’s say I now want to reverse this array with code, so it reads:

["Zaphod", "Arthur" ,"Ford"]

In Swift, I can do this using two methods:

  • By returning a value (a.k.a. “non-mutating”)
  • By changing in-place (a.k.a. “mutating”)

When returning a value, the original array isn’t changed. When changing in-place, no value is returned, and the original array will change.

Both concepts come in handy at different times, but using a method that returns a value when you expect none (and vice-versa) can be confusing.

Swift 3, therefore, uses a new naming convention:

  • Past participle verbs will return a value (“replaced”, “sorted”, “reversed”)
  • Nouns, and a verb’s imperative, will change in-place (“sort”, “replace”, “reverse”)

Differently put: if a method name includes a “-d” or “-ing”, it’ll return a value and doesn’t change in place.


var names = ["Ford", "Arthur", "Zaphod"]

names.reversed() // This will return the reversed array
names.reverse() // This will reverse the original variable "names"

names.sorted() // This will return the sorted array
names.sort() // This will sort the original array "names"

In Swift 2.2, sort() returned a sorted array and in Swift 3 that’s confusing, because now sort() sorts the array in place!

UpperCamelCase and lowerCamelCase

You’ve probably noticed: all Swift and Objective-C codes capitalize the first character of every new word in a method. That’s called upper camelcase or UpperCamelCase.

Specifically, classes, structs and enums use UpperCamelCase, and properties and parameter names use lowerCamelCase. There are exceptions however, such as:

URLRequest(URL: yourURL)

As of Swift 3, this will be:

URLRequest(url: yourURL)

(Note the lowercase “landscape” and “url”)

Likewise, properties will also go lowerCamelCase:

let color = UIColor.blue.cgColor // instead of .CGColor

It’s a small change, though!

__FUNCTION__ is now #function

Let’s be honest, you use the print() function to debug all sorts of stuff. Who doesn’t add this to the top of their code to know whether a method is executed or not?


(I do…)

In Swift 3, that will now be this:


The hash sytax is simply more modern, and in line with all other changes. These identifiers will change too:

  • __FILE__ -> #file
  • __LINE__ -> #line
  • __COLUMN__ -> #column
  • __FUNCTION__ -> #function
  • __DSO_HANDLE__ -> #dsohandle

Pro tip: use this for debugging, instead of the example above:

print("\(#file) --- \(#function) --- \(#line),\(#column)")

And when you have an error object of type NSError:

print("\(#file) --- \(#function) --- \(#line),\(#column) --- \(error.localizedDescription)")

Grand Central Dispatch is now Object-Oriented

Know Grand Central Dispatch (GCD)? It’s that bunch of squiggly lines and lower_snake_case methods you use to perform a task in a background thread.

Like this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) 
    // do some task

        // update some UI

In Swift 3, that’s now this:

DispatchQueue.global(attributes: [.qosDefault]).async {
    // do some task

    DispatchQueue.main.async(execute: { 
        // update some UI

As you can see, the dispatch queue now has its own class and methods. Moreover, you can chain queues and operations, and execute code as closures. More on GCD, here.

Useful Further Reading

Check out the list of all changes, here:

For further reading, check out the official Swift 3 documentation, here:

Written By: Reinder de Vries

Reinder de Vries is an indie app developer who teaches aspiring app developers and marketers how to build their own apps at LearnAppMaking.com. Since 2009 he has developed over 50 apps for iOS, Android and the web, and his code is used by millions of users all over the globe. When Reinder isn't building apps, he enjoys strong espresso and traveling.

Grab My Free iOS Development Course

Get complementary access to my course, Zero to App Store, and learn how you can build a real-time chat app with Firebase and Swift!

Yes, Send Me The Free Course!

Comments & Thoughts