Swift Handbook
Swift Handbook
Preface
The Swift Handbook
Conclusion
1
Preface
The Swift Handbook follows the 80/20 rule: learn in 20% of the time the
80% of a topic.
Enjoy!
2
The Swift Handbook
1. Introduction to Swift
2. Variables
3. Objects
4. Operators
4.1. Assignment operator
4.2. Arithmetic operators
4.3. Compound assignment operators
4.4. Comparison operators
4.5. Range operators
4.6. Logical operators
5. Conditionals:
5.1. if
5.2. switch
6.2. while
6.3. repeat-while
7. Comments
8. Semicolons
9. Numbers
10. Strings
11. Booleans
12. Arrays
13. Sets
14. Dictionaries
15. Tuples
16. Optionals and nil
17. Enumerations
18. Structures
3
19. Classes
20. Functions
21. Protocols
22. Where To Go From Here
1. Introduction to Swift
The Swift programming language was created by Apple in 2014, and it's the
official language to work with all the Apple Operating Systems lineup: iOS,
iPadOS, watchOS, macOS, tvOS.
Every value has a type assigned. The type of a value is always checked when
used as argument or returned, at compile time. If there is a mismatch, the
program will not compile.
The compiler of Swift is LLVM, and it is included within Xcode, the standard
IDE used to work with Apple software development.
Most of the software running on the iPhone and Mac today is based on
Objective-C code, even for official Apple apps, although Swift usage is gaining
traction year after year, and while Objective-C will be used for years to
maintain and improve existing apps, new applications are likely going to be
created with Swift.
4
This does not mean Objective-C is dead or not worth learning: Objective-C is
still an essential tool for any Apple developer.
That said, I am not going to cover Objective-C here, because we're focusing
on Swift.
In just 6 years, Swift has gone through 5 major versions, and we're now (at
the time of writing) at version 5.
The goal of this book is to get you up and running with Swift, starting from
zero.
2. Variables
Variables let us assign a value to a label, and are defined using the var
keyword:
5
var name = "Roger"
var age = 8
age = 9
Variables that you do not want to change can be defined as constants, using
the let keyword:
When you define a variable and you assign it a value, Swift implicitly infers
the type of it.
6
let age: Int = 8
but it's usual to let Swift infer it, and it's mostly done when you declare a
variable without initializing it.
age = 8
Once a variable is defined, it is bound to that type, and you cannot assign to it
a different type, unless you explicitly convert it.
var age = 8
age = "nine"
Int and String are just two of the built-in data types provided by Swift.
3. Objects
In Swift, everything is an object. Even the 8 value we assigned to the age
variable is an object.
7
In some languages, objects are a special type. But in Swift, everything is an
object and this leads to one particular feature: every value can receive
messages.
Each type can have multiple functions associated to it, which we call
methods.
For example, talking about the 8 number value, we can call its isMultiple
A type also has instance variables. For example the String type has the
instance variable count , which gives you the number of characters in a
string:
8
Swift has 3 different object types, which we'll see more in details later on:
classes, structs and enums.
Those are very different, but they have one thing in common: to object type,
we can add methods, and to any value, of any object type, we can send
messages.
4. Operators
We can use a wide set of operators to operate on values.
Then we can divide operators based on the kind of operation they perform:
assignment operator
arithmetic operators
compound assignment operators
comparison operators
range operators
logical operators
9
Note: Swift allows you to create your own operators and define how
operators work on your types you define.
var age = 8
var age = 8
var another = age
1 + 1 //2
2 - 1 //1
2 * 2 //4
4 / 2 //2
4 % 3 //1
4 % 2 //0
let hotTemperature = 20
let freezingTemperature = -20
10
4.3. Compound assignment operators
The compound assignment operators combine the assignment operator with
arithmetic operators:
+=
-=
*=
/=
%=
Example:
var age = 8
age += 1
==
!=
>
<
>=
<=
You can use those operators to get a boolean value ( true or false )
depending on the result:
let a = 1
let b = 2
a == b //false
a != b //true
a > b // false
a <= b //true
11
4.5. Range operators
Range operators are used in loops. They allow us to define a range:
let count = 3
for i in 0...count {
//loop body
}
Sample usage:
!condition1 //false
12
if condition1 && condition2 {
//if body
}
5. Conditionals:
5.1. if
if statements are the most popular way to perform a conditional check. We
use the if keyword followed by a boolean expression, followed by a block
containing code that is ran if the condition is true:
You can optionally wrap the condition validation into parentheses if you
prefer:
if (condition == true) {
// ...
}
13
if condition {
// runs if `condition` is `true`
}
or
if !condition {
// runs if `condition` is `false`
}
One thing that separates Swift from many other languages is that it prevents
bugs caused by erroneously doing an assignment instead of a comparison.
This means you can't do this:
if condition = true {
// The program does not compile
}
and the reason is that the assignment operator does not return anything, but
the if conditional must be a boolean expression.
5.2. switch
Switch statements are a handy way to create a conditional with multiple
options:
switch name {
case "Roger":
print("Hello, mr. Roger!")
default:
print("Hello, \(name)")
}
14
A switch in Swift needs to cover all cases. If the tag, name in this case, is a
string that can have any value, we need to add a default case, mandatory.
Otherwise with an enumeration, you can simply list all the options:
enum Animal {
case dog
case cat
}
switch animal {
case .dog:
print("Hello, dog!")
case .cat:
print("Hello, cat!")
}
var age = 20
switch age {
case 0..<18:
print("You can't drive!!")
default:
print("You can drive")
}
15
Example:
let num1 = 1
let num2 = 2
// smallerNumber == 1
The syntax is shorter than an if statement, and sometimes it might make
more sense to use it.
6. Loops
6.1. for-in
for-in loops can be used to iterate a specific amount of times, using a range
operator:
16
let list = ["a": 1, "b": 2, "c": 2]
for (key, value) in list {
// `key` contains the item key
// `value` contains the item value
}
6.2. while
A while loop can be used to iterate on anything, and will run while the
condition is true :
while [condition] {
//statements...
}
The condition is checked at the start, before the loop block is executed.
Example:
var item = 0
while item <= 3 { //repeats 3 times
print(item)
item += 1
}
6.3. repeat-while
A repeat-while loop in Swift is similar to the while loop, but in this case
the condition is checked at the end, after the loop block, so the loop block is
executed at least once. Then the condition is checked, and if it is evaluated as
true , the loop block is repeated:
repeat {
//statements...
} while [condition]
17
Example:
var item = 0
repeat { //repeats 3 times
print(item)
item += 1
} while item < 3
continue is used to stop the current iteration, and run the next iteration of
the loop.
Example:
7. Comments
A comment in Swift can take 2 forms: a single-line comment, and a multi-
line comment.
A single-line comment is
//this is a comment
18
and it can be put at the end of a line of code:
/* this
is
a multi-line
comment
*/
/* this
is
a /* nested */ multi-line
comment
*/
which is handy especially when commenting out large portions of code that
already contains multi-line comments.
8. Semicolons
In Swift, semicolons are optional.
You can write statements on separate lines, and you don't need to add a
semicolon:
You can add a semicolon, but it adds nothing meaningful in this case:
19
let list = ["a", "b", "c"];
var a = 2;
But if you want to write more than one statement on the same line, then you
need to add a semicolon:
var a = 2; let b = 3
9. Numbers
In Swift, numbers have 2 main types: Int and Double .
Both use 64 bits, on modern computers that work with 64 bits, and 32 bit on
32-bit platforms.
The range of values they can store depends on the platform used, and can be
retrieved using the int property of each type:
20
Then, in addition to Int and Double , we have lots of other numeric types,
mostly used to interact with APIs built in the past and that needed to interact
with C or Objective-C, and you must be aware that we have them:
UInt is like Int , but unsigned, and it ranges from 0 to Int.max * 2 .
Then using Cocoa APIs you might use other numeric types like CLong,
CGFloat, and more.
21
You will always use Int or Double in your code, and use those specific
types to particular cases.
Any of those types can always be converted to Int and Double types,
instantiating a number passing the value inside parentheses to Double() or
Int() :
10. Strings
Strings are one of the most popular tools in programming.
22
In Swift, a string can be defined using the string literal syntax:
We use double quotes. Single quotes are not valid string delimiters.
let age = 8
23
You can count the characters in a string using the count string property:
When you need to reference an item into the string, since strings in Swift are
unicode, we can't simply reference the letter o in let name = "Roger" using
name[1] . You need to work with indexes.
Any string provides the starting index with the startIndex property:
24
let name = "Roger"
let i = name.index(name.startIndex, offsetBy: 2)
name.suffix(from: i) //"ger"
name[i...] //"ger"
When you get a substring from a string, the type of the result is Substring ,
not String .
Substrings are more memory efficient, because you do not get a new string,
but the same memory structure is used behind the scenes, although you need
to be careful when you deal with strings a lot, as there are optimizations you
can implement.
11. Booleans
Swift provides the Bool type, which can have two values: true and false .
Booleans are especially useful with conditional control structures like if
25
var done = true
if done == true {
//code
}
12. Arrays
We use arrays to create a collection of items.
We can access the first item using the syntax list[0] , the second using
list[1] and so on.
The type can be inferred if you initialize the array at declaration time, like in
the case above.
Otherwise the type of values an array can include must be declared, in this
way:
26
A quick way to initialize an array is to use the range operator:
To get the number of items in the array, use the count property:
You can append an item at the end of the array using the append() method:
To remove one item from the array, use remove(at:) passing the index of
the element to remove:
27
removeLast() and removeFirst() are two handy ways to remove the last
and first element.
To remove all items from the array, you can use removeAll() or you can
assign an empty array:
There are a lot more methods, but those are the basic ones.
Arrays are equal when they contain the same elements, of the same type:
Arrays are passed by value, which means if you pass an array to a function, or
return it from a function, the array is copied.
13. Sets
Sets are used to create collections of non-repeated items.
While an array can contain many times the same item, you only have unique
items in a set.
28
let set: Set<Int> = [1, 2, 3]
Unlike arrays, there is no order or position in a set. Items are retrieved and
inserted randomly.
The way to print the content of a set ordered is to transform it into an array
using the sorted() method:
To get the number of items in the set, use the count property:
29
To remove one item from the array, use remove() passing the value of the
element:
To remove all items from the set, you can use removeAll():
set.removeAll()
Sets, like arrays, are passed by value, which means if you pass it to a function,
or return it from a function, the set is copied.
Sets are great to perform set math operations like intersection, union,
subtracting, and more.
intersection(_:)
symmetricDifference(_:)
union(_:)
subtracting(_:)
isSubset(of:)
isSuperset(of:)
isStrictSubset(of:)
isStrictSuperset(of:)
isDisjoint(with:)
14. Dictionaries
We use dictionaries to create a collection of key-value pairs.
30
Here is how to create a dictionary with 1 key-value pairs, where the key is a
String and the value is an Int:
In this case the type is inferred. You can also explicitly set the type at
declaration time:
In this example we create an empty dictionary of Int keys and String values:
//or
You can access the value assigned to a key using this syntax:
dict["Roger"] //8
dict["Syd"] //7
dict["Roger"] = 9
dict["Tina"] = 4
31
To remove a key/value paid, assign the value to nil :
dict["Tina"] = nil
dict.removeValue(forKey: "Tina")
To get the number of items in the dictionary, use the count property:
There are a lot of methods related to dictionaries, but those are the basic
ones.
15. Tuples
Tuples are used to group multiple values into a single collection. For example
we can declare a variable dog containing a String and an Int value:
32
let dog : (String, Int) = ("Roger", 8)
But as with any other variable, the type can be inferred during initialization:
dog.name //"Roger"
dog.age //8
and if you need to just get one of the values, you can use the special
underscore keyword to ignore the other ones:
33
var a = 1
var b = 2
(a, b) = (b, a)
//a == 2
//b == 1
When you don't know if a value will be present or absent, you declare the
type as an optional.
The optional wraps another value, with its own type. Or maybe not.
We declare an optional adding a question mark after its type, like this:
Now value is not an Int value. It's an optional wrapping an Int value.
To find out if the optional wraps a value, you must unwrap it.
Swift methods often return an optional. For example the Int type initializer
accepts a string, and returns an Int optional:
34
This is because it does not know if the string can be converted to a number.
If the optional does not contain a value, it evaluates as nil , and you cannot
unwrap it:
35
nil is a special value that cannot be assigned to a variable. Only to an
optional:
36
You typically use if statements to unwrap values in your code, like this:
17. Enumerations
Enumerations are a way to group a set of different options, under a common
name.
Example:
37
enum Animal {
case dog
case cat
case mouse
case horse
}
you can later decide which value to assign it using this syntax:
enum Animal {
case dog
case cat
case mouse
case horse
}
switch animal {
case .dog: print("dog")
case .cat: print("cat")
default: print("another animal")
}
38
You can also define an enum on a single line:
enum Animal {
case dog, cat, mouse, horse
}
And you can also add type declaration to the enumeration, and each case has
a value of that type assigned:
Once you have a variable, you can get this value using its rawValue property:
animal.rawValue //1
Enumerations are a value type. This means they are copied when passed to a
function, or when returned from a function. And when we assign a variable
pointing to an enumeration to another variable.
18. Structures
Structures are one essential Swift concepts.
39
Structures are everywhere in Swift. Even the built-in types are structures.
In most languages, objects can only be created from classes. Swift has classes,
too, but you can create objects also from structures and the official
documentation advises to prefer structures because they are easier to use.
A struct can have properties. A struct can have methods (functions) A struct
can define subscripts A struct can define initializers A struct can conform to
protocols A struct can be extended
One important thing classes allow is inheritance, so if you need that, you
have classes.
struct Dog {
struct Dog {
var age = 8
var name = "Roger"
}
This structure definition defines a type. To create a new instance with this
type, we use this syntax:
Once you have an instance, you can access its properties using the dot syntax:
40
let roger = Dog()
roger.age
roger.name
roger.age = 9
You can also create a struct instance passing the values of the properties:
struct Dog {
var age = 8
var name = "Roger"
func bark() {
print("\(name): wof!")
}
}
41
struct Dog {
var age = 8
var name = "Roger"
func bark() {
print("\(name): wof!")
}
static func hello() {
print("Hello I am the Dog struct")
}
}
Invoked as Dog.hello()
Structures are a value type. This means they are copied when passed to a
function, or when returned from a function. And when we assign a variable
pointing to a structure to another variable.
All types in Swift are defined as structures: Int, Double, String, arrays and
dictionaries, and more, are structures.
19. Classes
Classes are a bit similar to structures, but they have some key differences.
class Dog {
class Dog {
var age = 0
}
42
A class definition defines a type. To create a new instance with this type, we
use this syntax:
Once you have an instance, you can access its properties using the dot syntax:
roger.age = 9
One big difference is that classes are reference types. Structures (and
enumerations) are value types.
This means that assigning a class instance to another variable does not copy
the instance. Both variables point to the same instance:
class Dog {
var age = 0
}
roger.age = 9
//syd.age == 9
This also means we can define a reference to a class using let , and we can
change its properties, as you saw in the example above.
43
Contrary to structs, we must define an initializer in order to initialize the
values when we create an instance:
class Dog {
var age : Int
init(age: Int) {
self.age = age
}
}
You can only declare properties without initializing them if you have an
initializer.
See the use of self . We need it because age is both an instance property
and the init(age:) method parameter. self.age references the age
instance property.
class Dog {
var age = 8
var name = "Roger"
func bark() {
print("\(name): wof!")
}
}
44
class Dog {
var age = 8
var name = "Roger"
func bark() {
print("\(name): wof!")
}
static func hello() {
print("Hello I am the Dog struct")
}
}
Invoked as Dog.hello()
A class can inherit all the properties and methods from another class.
class Animal {
var age: Int
}
Not every animal has a name. Dogs have a name. So we create a Dog class
extending from Animal :
Now we must add an initializer for both classes. In the Dog case, after we do
the class-specific initialization, we can call the parent class initializer using
super.init() :
45
class Animal {
var age: Int
init(age: Int) {
self.age = age
}
}
20. Functions
Your program's code is organized into functions.
func bark() {
print("woof!")
}
46
bark()
A function can accept parameters. Each parameter has a name, and a type:
We use the name of the parameter when we call the function, to pass in its
value:
bark(times: 3)
When we call the function we must pass all the parameters defined.
47
func bark(times: Int, repeatBark: Bool) {
for index in 0..<times {
if repeatBark == true {
print("woof woof!")
} else {
print("woof!")
}
}
}
This is because we can have multiple functions with the same name, but
different set of parameters.
It's common in Swift and iOS APIs to have the first parameter with no label,
and the other parameters labeled.
It makes for a nice and expressive API, when you design the names of the
function and the parameters nicely.
You can only return one value from a function. If you need to return multiple
values, it's common to return a tuple:
48
func bark() -> (String, Int) {
print("woof!")
return ("barked successfully", 1)
}
Functions can be nested inside other functions. When this happens, the inner
function is invisible to outside the outer function.
21. Protocols
A protocol is a way to have different objects, of different types, have a
common set of functionality.
protocol Mammal {
49
A protocol can define properties and methods, without providing values and
implementations, and a struct/class must implement them:
protocol Mammal {
var age: Int { get set }
func walk()
}
The property can be defined as get or get set . If it's get , the property
must be implemented as read only, with a getter.
Any type that adopts the protocol must conform to the protocol by
implementing those methods or providing those properties:
Notice that for classes, this is the same syntax used to define a superclass. If
there is a superclass, list it as the first item in the list, after the colon.
50
22. Where To Go From Here
I hope this little handbook was useful to shine a light on how to get started
with Swift, and I hope you are now interested to learn more about it!
51
Conclusion
Thanks a lot for reading this book.
52