What’s New in Swift 5?

Swift 5 is finally available in Xcode 10.2! This release brings ABI stability and improves the language with some long-awaited features. See what’s new! By Cosmin Pupăză.

Leave a rating/review
Download materials
Save for later
Share

Great news! Swift 5 is finally available in Xcode 10.2! This release brings ABI stability and improves the language with some long-awaited features.

In this tutorial, you’ll learn about the most important changes in Swift 5. Swift 5 requires Xcode 10.2, so make sure to install it before getting started.

Getting Started

Swift 5 is source compatible with Swift 4.2, but isn’t binary compatible with earlier Swift releases. However, future releases will be binary compatible with Swift 5 thanks to ABI stability.

ABI stability enables binary compatibility between apps and libraries compiled with different Swift versions. The Swift standard library and runtime get embedded in the OS, so apps don’t distribute their own copy of the libraries on any platform. This leads to better tool decoupling and OS integration.

You also need ABI stability to distribute binary frameworks that work across multiple Swift versions. This requires module format stability, which stabilizes the module file containing the compiler’s representation of the framework’s public interfaces.

You’ll find Swift Evolution proposal numbers like [SE-0001] in each section of the tutorial. You can learn more about each new change by exploring each proposal link.

The best way to follow this tutorial is to try out the new features in a playground.

Fire up Xcode 10.2 and select File ▸ New ▸ Playground. Set the platform to iOS and the template to Blank. Name and save it anywhere you want. Time to get started!

Note: Need a quick reminder of the Swift 4.2 highlights? Check out the Swift 4.2 tutorial: What’s New in Swift 4.2?

Language Improvements

There are many language features in Swift 5, such as dynamic callable types, handling future enumeration and more.

Testing Integer Multiples

In Swift 4.2, you determine whether a number is a multiple of another with the remainder operator:

let firstNumber = 4
let secondNumber = 2
if secondNumber != 0 && firstNumber % secondNumber == 0 {
  print("\(secondNumber) * \(firstNumber / secondNumber) = \(firstNumber)")
}

How this code works:

  1. Check that secondNumber isn’t 0.
  2. Check that dividing firstNumber by secondNumber returns a remainder of 0.
  3. Perform the divide operation.

You must check that secondNumber isn’t 0, because % throws an error if it is.

Swift 5 simplifies this by adding isMultiple(of:) to BinaryInteger [SE-0225]:

if firstNumber.isMultiple(of: secondNumber) {
  print("\(secondNumber) * \(firstNumber / secondNumber) = \(firstNumber)")
}

isMultiple(of:) works even if you pass it an argument of 0, and the resulting code is much cleaner.

Escaping Raw Strings

Swift 4.2 uses escape sequences to represent backslashes and quote marks in strings:

let escape = "You use escape sequences for \"quotes\"\\\"backslashes\" in Swift 4.2."
let multiline = """
                You use escape sequences for \"\"\"quotes\"\"\"\\\"\"\"backslashes\"\"\"
                on multiple lines
                in Swift 4.2.
                """

Swift 5 adds raw strings. You add # at the beginning and end of the string so you can use backslashes and quote marks without issue. [SE-0200]:

let raw = #"You can create "raw"\"plain" strings in Swift 5."#
let multiline = #"""
                You can create """raw"""\"""plain""" strings
                on multiple lines
                in Swift 5.
                """#

When using string interpolation in raw strings, you have to use a pound sign after the backslash:

let track = "Nothing Else Matters"
print(#"My favorite tune\song is \#(track)."#)

There are some cases when you need to use more than one # at the beginning and end of the string:

let hashtag = ##"You can use the Swift "hashtag" #swift in Swift 5."##

In the code above, you add ## at the beginning and end of hashtag so that you can represent # inside the string. The number of #s used at the beginning of the string must match the number at the end of it.

In Swift 4.2, you escape backslashes inside regular expressions as follows:

// 1
let versions = "3 3.1 4 4.1 4.2 5"
let range = NSRange(versions.startIndex..., in: versions)
// 2
let regex = try! NSRegularExpression(pattern: "\\d\\.\\d")
// 3
let minorVersions = regex.matches(in: versions, range: range)
// 4
minorVersions.forEach { print(versions[Range($0.range, in:  versions)!]) }

Here’s how this code works:

  1. Declare versions and define a range that covers the whole string.
  2. Define a regular expression which matches all minor Swift releases in versions.
  3. Determine minor version ranges with matches(in:options:range:).
  4. Use the ranges to get the minor releases from versions.

Swift 5 simplifies regular expressions with raw strings:

let regex = try! NSRegularExpression(pattern: #"\d\.\d"#)

In this code, you write regex using half the number of backslashes, because you don’t need to escape backslashes in raw strings.

No extra backslashes in regular expressions!

No extra backslashes in regular expressions!

No extra backslashes in regular expressions!

Note: Need more details about how regular expressions work in Swift? Check out the regular expressions tutorial: An Introduction to Regular Expressions.

Using New Character Properties

Swift 4.2 requires workarounds for common tasks when working with characters:

let id = "ID10"
var digits = 0
id.forEach { digits += Int(String($0)) != nil ? 1 : 0 }
print("Id has \(digits) digits.")

In this code, you determine how many digits id has by first casting each character to String, then to Int.

However, Swift 5 adds properties to Character which make characters easier to use [SE-0221]:

id.forEach { digits += $0.isNumber ? 1 : 0 }

In this case, you use isNumber to check if every character is a digit. Have a look at the proposal for other properties you can use.

Using New Unicode Scalar Properties

In Swift 4.2, you implement text processing algorithms for unicode scalars as follows:

let username = "bond007"
var letters = 0
username.unicodeScalars.forEach { 
  letters += (65...90) ~= $0.value || (97...122) ~= $0.value ? 1 : 0
}
print("Username has \(letters) letters.")

In this code, you compute how many letters username has by checking if each character’s unicode scalar represents a small letter or a capital one.

Swift 5 adds properties to unicode scalars, which simplify text processing [SE-0211]:

username.unicodeScalars.forEach { letters += $0.properties.isAlphabetic ? 1 : 0 }

In this code, you use isAlphabetic to check if every character is a digit. The linked proposal shows all the properties you can check.

Cosmin Pupăză

Contributors

Cosmin Pupăză

Author

Sarah Reichelt

Tech Editor

Ryan Dube

Editor

Martín Riera

Illustrator

Marin Bencevic

Final Pass Editor

Richard Critz

Team Lead

Over 300 content creators. Join our team.