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ă.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
What’s New in Swift 5?
25 mins
- Getting Started
- Language Improvements
- Testing Integer Multiples
- Escaping Raw Strings
- Using New Character Properties
- Using New Unicode Scalar Properties
- Removing Subsequences
- Dictionary Updates
- Compacting Dictionaries
- Renaming Dictionary Literals
- Numeric Protocol Updates
- String Interpolation Updates
- Handling Future Enumeration Cases
- Adding Result to the Standard Library
- Conforming Never to Equatable and Hashable
- Dynamically Callable Types
- Swift Package Manager Updates
- Platform Deployment Settings
- Target Build Settings
- Dependency Mirroring
- Miscellaneous Bits and Pieces
- Making Codable Ranges
- Flattening Nested Optionals
- Removing Customization Points From Collections
- Identity Key Paths
- Initializing Literals Through Coercion
- Build Configuration Updates
- Using Variadic Parameters for Enumeration Cases With Associated Values
- Deprecating String Index Encoded Offsets
- New Pointer Methods
- SIMD Vector Updates
- Where to Go From Here?
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!
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:
- Check that
secondNumber
isn’t 0. - Check that dividing
firstNumber
bysecondNumber
returns a remainder of 0. - 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:
- Declare
versions
and define arange
that covers the whole string. - Define a regular expression which matches all minor Swift releases in
versions
. - Determine minor version ranges with
matches(in:options:range:)
. - 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.
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.
Removing Subsequences
Swift 4.2 returns SubSequence
from Sequence
customization points as follows:
extension Sequence {
func remove(_ s: String) -> SubSequence {
guard let n = Int(s) else {
return dropLast()
}
return dropLast(n)
}
}
let sequence = [5, 2, 7, 4]
sequence.remove("2") // [5, 2]
sequence.remove("two") // [5, 2, 7]
In this case, remove(_:)
drops the last n
elements from the sequence if s
is an Int
or the last element.
Swift 5 replaces SubSequence
with concrete types in sequences [SE-0234]:
extension Sequence {
func remove(_ s: String) -> [Element] {
guard let n = Int(s) else {
return dropLast()
}
return dropLast(n)
}
}
In this code, remove(_:)
returns [Element]
since dropLast()
and dropLast(_:)
return [Element]
.
Dictionary Updates
Swift 5 brings some long-awaited improvements to dictionaries:
Compacting Dictionaries
Swift 4.2 uses mapValues
, filter
and reduce
to filter nil
values from dictionaries as follows:
let students = ["Oana": "10", "Nori": "ten"]
let filterStudents = students.mapValues(Int.init)
.filter { $0.value != nil }
.mapValues { $0! }
let reduceStudents = students.reduce(into: [:]) { $0[$1.key] = Int($1.value) }
This code uses mapValues
with filter
or reduce
to determine the students with valid grades from students
. Both approaches require multiple dictionary passes and complicate your code.
Swift 5 uses compactMapValues(_:)
for a more efficient solution [SE-0218]:
let mapStudents = students.compactMapValues(Int.init)
It accomplishes the same thing in much fewer lines of code, neat!
Renaming Dictionary Literals
Swift 4.2 uses DictionaryLiteral
to declare dictionaries as follows:
let pets: DictionaryLiteral = ["dog": "Sclip", "cat": "Peti"]
DictionaryLiteral
isn’t a dictionary or a literal. It’s a list of key-value pairs.
Swift 5 renames DictionaryLiteral
to KeyValuePairs
[SE-0214]:
let pets: KeyValuePairs = ["dog": "Sclip", "cat": "Peti"]
Numeric Protocol Updates
Swift 4.2 implements Numeric
for vectors:
// 1
struct Vector {
let x, y: Int
init(_ x: Int, _ y: Int) {
self.x = x
self.y = y
}
}
// 2
extension Vector: ExpressibleByIntegerLiteral {
init(integerLiteral value: Int) {
x = value
y = value
}
}
// 3
extension Vector: Numeric {
var magnitude: Int {
return Int(sqrt(Double(x * x + y * y)))
}
init?<T>(exactly value: T) {
x = value as! Int
y = value as! Int
}
static func +(lhs: Vector, rhs: Vector) -> Vector {
return Vector(lhs.x + rhs.x, lhs.y + rhs.y)
}
static func +=(lhs: inout Vector, rhs: Vector) {
lhs = lhs + rhs
}
static func -(lhs: Vector, rhs: Vector) -> Vector {
return Vector(lhs.x - rhs.x, lhs.y - rhs.y)
}
static func -=(lhs: inout Vector, rhs: Vector) {
lhs = lhs - rhs
}
static func *(lhs: Vector, rhs: Vector) -> Vector {
return Vector(lhs.x * rhs.y, lhs.y * rhs.x)
}
static func *=(lhs: inout Vector, rhs: Vector) {
lhs = lhs * rhs
}
}
// 4
extension Vector: CustomStringConvertible {
var description: String {
return "(\(x) \(y))"
}
}
Here’s how this code works:
- Declare
x
,y
andinit(_:_:)
forVector
. - Implement
init(integerLiteral:)
to conformVector
toExpressibleByIntegerLiteral
as a requirement forNumeric
conformance. - Conform
Vector
toNumeric
by defining the vector’smagnitude
, declaringinit(exactly:)
and implementing+(lhs:rhs:)
,+=(lhs:rhs:)
,-(lhs:rhs:)
,-=(lhs:rhs:)
,*(lhs:rhs:)
,*=(lhs:rhs:)
. - Implement
description
to conformVector
toCustomStringConvertible
.
The code above enables you to work with vectors easily:
var first = Vector(1, 2) // (1,2)
let second = Vector(3, 4) // (3,4)
let third = first + second // (4,6)
first += second // (4,6)
let fourth = first - second // (1,2)
first -= second // (1,2)
Swift 5 implements AdditiveArithmetic
for vectors, because you can’t define the cross product of 2D vectors [SE-0233]. It doesn’t require ExpressibleByIntegerLiteral
conformance:
extension Vector: AdditiveArithmetic {
static var zero: Vector {
return Vector(0, 0)
}
static func +(lhs: Vector, rhs: Vector) -> Vector {
return Vector(lhs.x + rhs.x, lhs.y + rhs.y)
}
static func +=(lhs: inout Vector, rhs: Vector) {
lhs = lhs + rhs
}
static func -(lhs: Vector, rhs: Vector) -> Vector {
return Vector(lhs.x - rhs.x, lhs.y - rhs.y)
}
static func -=(lhs: inout Vector, rhs: Vector) {
lhs = lhs - rhs
}
}
In this code, you conform Vector
to AdditiveArithmetic
by defining a zero
and implementing +(lhs:rhs:)
, +=(lhs:rhs:)
, -(lhs:rhs:)
, -=(lhs:rhs:)
.
String Interpolation Updates
Swift 4.2 implements string interpolation by interpolating segments:
let language = "Swift"
let languageSegment = String(stringInterpolationSegment: language)
let space = " "
let spaceSegment = String(stringInterpolationSegment: space)
let version = 4.2
let versionSegment = String(stringInterpolationSegment: version)
let string = String(stringInterpolation: languageSegment, spaceSegment, versionSegment)
In this code, the compiler first wraps each literal segment and then interpolates one with init(stringInterpolationSegment:)
. Then, it wraps all segments together with init(stringInterpolation:)
.
Swift 5 takes a completely different approach [SE-0228]:
// 1
var interpolation = DefaultStringInterpolation(
literalCapacity: 7,
interpolationCount: 1)
// 2
let language = "Swift"
interpolation.appendLiteral(language)
let space = " "
interpolation.appendLiteral(space)
let version = 5
interpolation.appendInterpolation(version)
// 3
let string = String(stringInterpolation: interpolation)
Here’s what this code does:
- Define a
DefaultStringInterpolation
instance with a certain capacity and interpolation count. - Call
appendLiteral(_:)
orappendInterpolation(_:)
to add literals and interpolated values tointerpolation
. - Produce the final interpolated string by calling
init(stringInterpolation:)
.
Handling Future Enumeration Cases
Swift 4.2 doesn’t handle new enumeration cases properly, as you can see below:
// 1
enum Post {
case tutorial, article, screencast, course
}
// 2
func readPost(_ post: Post) -> String {
switch post {
case .tutorial:
return "You are reading a tutorial."
case .article:
return "You are reading an article."
default:
return "You are watching a video."
}
}
// 3
let screencast = Post.screencast
readPost(screencast) // "You are watching a video."
let course = Post.course
readPost(course) // "You are watching a video."
Here’s what happens in the code above:
- Define all types of blog posts on the website.
- To make
switch
exhaustive, adddefault
. - Handle
.screencast
and.course
withdefault
since screencasts and courses are videos.
The following is how handling podcasts works in Swift 4.2:
enum Post {
case tutorial, article, podcast, screencast, course
}
let podcast = Post.podcast
readPost(podcast) // "You are watching a video."
In this code, you handle .podcast
with default
, even though podcasts aren’t videos. Swift 4.2 doesn’t warn you about this because the switch
is exhaustive.
Swift 5 takes care of added enumeration cases [SE-0192]:
func readPost(_ post: BlogPost) -> String {
switch post {
case .tutorial:
return "You are reading a tutorial."
case .article:
return "You are reading an article."
@unknown default:
return "You are reading a blog post."
}
}
readPost(screencast) // "You are reading a blog post."
readPost(course) // "You are reading a blog post."
readPost(podcast) // "You are reading a blog post."
In this code, you mark default
as @unknown
, and Swift warns you that switch
isn’t exhaustive. default
handles .screencast
, .course
and .podcast
because screencasts, courses and podcasts are blog posts.
Adding Result to the Standard Library
Swift 5 adds Result
to the standard library [SE-0235]:
// 1
enum ConnectionError: Error {
case noNetwork, noDatabase
}
// 2
let networkSuccess = Result<String, ConnectionError>.success("Network connected!")
let databaseSuccess = Result<String, ConnectionError>.success("Database connected!")
let networkFailure = Result<String, ConnectionError>.failure(.noNetwork)
let databaseFailure = Result<String, ConnectionError>.failure(.noDatabase)
let sameSuccess = networkSuccess == databaseSuccess
let sameFailure = networkFailure == databaseFailure
let success: Set = [networkSuccess, databaseSuccess]
let failure: Set = [networkFailure, databaseFailure]
let successDictionary = [
networkSuccess: try! networkSuccess.get(),
databaseSuccess: try! databaseSuccess.get()
]
let failureDictionary = [
networkFailure: ConnectionError.noNetwork,
databaseFailure: ConnectionError.noDatabase
]
Here’s how this code works:
- Declare the most common connection errors.
- Compare connection results, add them to sets. You use these sets as keys for dictionaries, since
Result
implementsEquatable
andHashable
.
Conforming Never to Equatable and Hashable
Swift 5 conforms Never
to Equatable
and Hashable
[SE-0215]:
let alwaysSucceeds = Result<String, Never>.success("Network connected!")
let neverFails = Result<String, Never>.success("Database connected!")
let alwaysFails = Result<Never, ConnectionError>.failure(.noNetwork)
let neverSucceeds = Result<Never, ConnectionError>.failure(.noDatabase)
let sameValue = alwaysSucceeds == neverFails
let sameError = alwaysFails == neverSucceeds
let alwaysSuccess: Set = [alwaysSucceeds, neverFails]
let alwaysFailure: Set = [alwaysFails, neverSucceeds]
let alwaysSuccessDictionary = [
alwaysSucceeds: try! alwaysSucceeds.get(),
neverFails: try! neverFails.get()
]
let alwaysFailureDictionary = [
alwaysFails: ConnectionError.noNetwork,
neverSucceeds: ConnectionError.noDatabase
]
In this code, you define connection results that always return values or errors, compare them, add them to sets and use them as dictionary keys.
Dynamically Callable Types
Swift 5 defines dynamically callable types that interoperate with scripting languages like Python or Ruby [SE-0216]:
// 1
@dynamicCallable
class DynamicFeatures {
// 2
func dynamicallyCall(withArguments params: [Int]) -> Int? {
guard !params.isEmpty else {
return nil
}
return params.reduce(0, +)
}
func dynamicallyCall(withKeywordArguments params: KeyValuePairs<String, Int>) -> Int? {
guard !params.isEmpty else {
return nil
}
return params.reduce(0) { $1.key.isEmpty ? $0 : $0 + $1.value }
}
}
// 3
let features = DynamicFeatures()
features() // nil
features(3, 4, 5) // 12
features(first: 3, 4, second: 5) // 8
The code above works as follows:
- Mark
DynamicFeatures
as@dynamicCallable
to make it a dynamically callable type. - To make
DynamicFeatures
conform to@dynamicCallable
, implementdynamicallyCall(withArguments:)
anddynamicallyCall(withKeywordArguments:)
. - Invoke
features
using normal syntax, and the compiler callsdynamicallyCall(withArguments:)
ordynamicallyCall(withKeywordArguments:)
.
Swift Package Manager Updates
Swift 5 adds a few features to the Swift Package Manager:
Platform Deployment Settings
Swift 5 allows you to define the minimum required platform deployment target version in Package.swift [SE-0236]:
let package = Package(name: “Package”, platforms: [
.macOS(.v10_14),
.iOS(.v12),
.tvOS(.v12),
.watchOS(.v5)
])
You use macOS()
, iOS()
, tvOS()
and watchOS()
in SupportedPlatform
to set the minimum required platform version for package
.
Target Build Settings
Swift 5 declares target-specific build settings in Package.swift. They customize how the package manager invokes build tools during target builds [SE-0238].
Dependency Mirroring
Swift 5 brings dependency mirroring to the Swift Package Manager [SE-0219].
swift package config set-mirror --package-url <package> --mirror-url <mirror>
Mirrors give you access to dependencies, even if the original source becomes unavailable or gets deleted.
set-mirror
updates a dependency with a mirror, which replaces all other ones.
Use unset-mirror
to remove mirrors from dependencies:
swift package config unset-mirror --package-url <package>
swift package config unset-mirror —mirror-url <mirror>
swift package config unset-mirror --all
Miscellaneous Bits and Pieces
Swift 5 adds a few other much-needed features and improvements:
Making Codable Ranges
Swift 5 adds Codable
conformance to ranges [SE-0239]:
let temperature = 0...10
let encoder = JSONEncoder()
let data = try! encoder.encode(temperature)
let decoder = JSONDecoder()
let temperatureRange = try! decoder.decode(ClosedRange<Int>.self, from: data)
You encode temperature
with JSONEncoder
and decode data
with JSONDecoder
since ranges implement Codable
by default in Swift 5.
Flattening Nested Optionals
Swift 4.2 creates nested optionals with try?
:
extension Int {
// 1
enum DivisionError: Error {
case divisionByZero
}
// 2
func divideBy(_ number: Int) throws -> Int {
guard number != 0 else {
throw DivisionError.divisionByZero
}
return self / number
}
}
// 3
let number: Int? = 10
let division = try? number?.divideBy(2)
if let division = division,
let final = division {
print(final)
}
Here’s what this code does:
- Extend
Int
withDivisionError
. -
divideBy(_:)
throws.divisionByZero
ifnumber
is 0. - Unwrap
division
twice since it’s anInt??
.
Swift 5 handles this differently [SE-0230]:
if let division = division {
print(division)
}
try?
in Swift 5 doesn’t create nested optionals, so you unwrap division
once since it’s an Int?
.
Removing Customization Points From Collections
You have access to customization points from Collection
in Swift 4.2:
extension Array {
var first: Element? {
return !isEmpty ? self[count - 1] : nil
}
var last: Element? {
return !isEmpty ? self[0] : nil
}
}
let names = ["Cosmin", "Oana", "Sclip", "Nori"]
names.first // "Nori"
names.last // "Cosmin"
In this code, first
returns the last name from names
, and last
returns the first element of the array.
Both computed properties don’t work as expected, so Swift 5 removes their customization points from collections [SE-0232].
Identity Key Paths
Swift 4.2 uses .self
to access values:
class Tutorial {
let title: String
let author: String
init(title: String, author: String) {
self.title = title
self.author = author
}
}
var tutorial = Tutorial(title: "What's New in Swift 5.0?", author: "Cosmin Pupaza")
tutorial.self = Tutorial(title: "What's New in Swift 5?", author: "Cosmin Pupăză")
In this code, you use .self
to change the tutorial’s title
and author
in one go.
Swift 5 adds identity key paths for value access [SE-0227]:
tutorial[keyPath: \.self] = Tutorial(
title: "What's New in Swift 5?",
author: "Cosmin Pupăză")
In this code, you use \.self
to update tutorial
.
Initializing Literals Through Coercion
In Swift 5, literal initializers coerce the literal to its type if the type conforms to the literal protocol [SE-0213]:
let value = UInt64(0xFFFF_FFFF_FFFF_FFFF)
In Swift 4.2, the line of code above produces an overflow error at compile time.
Build Configuration Updates
Swift 4.2 uses >=
in compilation conditions:
let favoriteNumber = 10
var evenNumber = true
#if !swift(>=5)
evenNumber = favoriteNumber % 2 == 0
#else
evenNumber = favoriteNumber.isMultiple(of: 2)
#endif
#if !compiler(>=5)
evenNumber = favoriteNumber % 2 == 0
#else
evenNumber = favoriteNumber.isMultiple(of: 2)
#endif
These conditions check if the Swift version is greater than or equal to 5 and compile those bits of code if the condition is met.
Swift 5 adds <
for cleaner conditions [SE-0224]:
#if swift(<5)
evenNumber = favoriteNumber % 2 == 0
#else
evenNumber = favoriteNumber.isMultiple(of: 2)
#endif
#if compiler(<5)
evenNumber = favoriteNumber % 2 == 0
#else
evenNumber = favoriteNumber.isMultiple(of: 2)
#endif
Using Variadic Parameters for Enumeration Cases With Associated Values
You can use variadic parameters for enumeration cases with associated values in Swift 4.2:
enum BlogPost {
case tutorial(_: String...)
case article(_: String...)
}
You use String…
for tutorials and articles details. This isn't possible anymore in Swift 5, so you should use arrays instead:
enum BlogPost {
case tutorial([String])
case article([String])
}
You use [String]
to set tutorials and articles details this time.
Deprecating String Index Encoded Offsets
Swift 4.2 strings are encoded using UTF-16. As a result encodedOffset
returns an offset into the UTF-16 string:
let swiftVersion = "Swift 4.2"
let offset = swiftVersion.endIndex.encodedOffset
Here you get the offset
of endIndex
in swiftVersion
. This doesn’t work for the UTF-8 string encoding employed in Swift 5, so Swift 5 replaces encodedOffset
with utf16Offset(in:)
to handle both cases [SE-0241]:
let swiftVersion = "Swift 5"
let offset = swiftVersion.endIndex.utf16Offset(in: swiftVersion)
New Pointer Methods
Swift 5 adds withContiguousStorageIfAvailable(_:)
to Sequence
and withContiguousMutableStorageIfAvailable(_:)
to MutableCollection
to provide generic implementations for withUnsafeBufferPointer(_:)
and withUnsafeMutableBufferPointer(_:)
in protocol extensions [SE-0237].
SIMD Vector Updates
Swift 5 adds operations on SIMD types for processors to the standard library. They provide low-level support for SIMD vectors and matrices. They also simplify the Objective-C, C and C++ implementations of <simd/simd.h>
[SE-0229].
Where to Go From Here?
You can download the final playground using the Download Materials link at the top or bottom of this tutorial.
Swift 5 adds many cool features to Swift 4.2 and makes the language ABI stable. This is an important milestone in the language’s evolution, since there will be fewer changes from now on.
You can read more about the changes in this version of Swift on the official Swift CHANGELOG or the Swift standard library diffs.
You can also check out the Swift Evolution proposals to see what changes are coming in the next Swift version. Here, you can offer feedback for current proposals under review and even pitch a proposal yourself!
What do you like or dislike about Swift 5 so far? Let us know in the forum discussion below!
All videos. All books.
One low price.
A Kodeco subscription is the best way to learn and master mobile development — plans start at just $19.99/month! Learn iOS, Swift, Android, Kotlin, Flutter and Dart development and unlock our massive catalog of 50+ books and 4,000+ videos.
Learn more