Swift Tutorial

Swift Introduction

The Swift Programming Language (Swift 5.3)


Swift Playground

Simple Value

“On a Mac with Xcode installed, or on an iPad with Swift Playgrounds, you can open this chapter as a playground. Playgrounds allow you to edit the code listings and see the result immediately.”

After download the sample playground file, click on the run button on the left and bottom screen. Then you can see the running result on the right screen. Playground is a kind of file like Jupyter notebook or R Markdown.


Hello Swift

You can show result on the next line of the code. And edit the code you like.


Docstring

Use // for one line comment.
Use /** and */ for multi-line comments.

Swift
1
// This is one line comment.
Swift
1
2
3
/**
This is multi-line comments
*/

let & var

Use let to make a constant and var to make a variable. The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once. This means you can use constants to name a value that you determine once but use in many places.

Swift
1
2
3
var myVariable = 42
myVariable = 50
let myConstant = 42

You cannot modify a constant.

Swift
1
2
myConstant = 50
// Cannot assign to value: 'myConstant' is a 'let' constant

A constant or variable must have the same type as the value you want to assign to it. However, you don’t always have to write the type explicitly. Providing a value when you create a constant or variable lets the compiler infer its type. In the example above, the compiler infers that myVariable is an integer because its initial value is an integer.

If the initial value doesn’t provide enough information (or if isn’t an initial value), specify the type by writing it after the variable, separated by a colon.

Swift
1
2
3
4
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
let four: Float = 4

Convert Data Type through constructor

Values are never implicitly converted to another type. If you need to convert a value to a different type, explicitly make an instance of the desired type. Like type constructor in Python.

Swift
1
2
3
let label = "The width is " // constant string
let width = 94 // constant int
let widthLabel = label + String(width) // You cannot use string + int, so we convert the data type from int to string
Swift
1
2
let widthLabel = label + width
// Binary operator '+' cannot be applied to operands of type 'String' and 'Int'

Convert Data Type through \

There’s an even simpler way to include values in strings: Write the value in parentheses, and write a backslash (\) before the parentheses. For example:

Swift
1
2
3
4
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

You cannot multiply int and Float

Swift
1
2
3
4
let applePrice = 0.99
applePrice
let applesTotalPrice = "Total apple prices is \(apples * applePrice)"
// Cannot convert value of type 'Int' to expected argument type 'Double'

Use \() to include a floating-point calculation in a string and to include someone’s name in a greeting.

Swift
1
2
let applesTotalPrice = "Total apple prices is \(Double(apples) * applePrice)"
// Total apple prices is 2.9699999999999998

Multiple Lines

Use three double quotation marks (""") for strings that take up multiple lines. Indentation at the start of each quoted line is removed, as long as it matches the indentation of the closing quotation marks. For example:

Swift
1
2
3
4
5
6
7
8
9
let quotation = """
I said "I have \(apples) apples."
And then I said "I have \(apples + oranges) pieces of fruit."
"""
print(quotation)
/**
I said "I have 3 apples."
And then I said "I have 8 pieces of fruit."
*/

array & dictionaries

Create arrays and dictionaries using brackets ([]), and access their elements by writing the index or key in brackets. A comma is allowed after the last element.


array

Create an array.

Swift
1
2
3
var shoppingList = ["catfish", "water", "tulips"]
print(shoppingList)
// ["catfish", "water", "tulips"]

Replace element in array.

Swift
1
2
3
shoppingList[1] = "bottle of water"
print(shoppingList)
// ["catfish", "bottle of water", "tulips"]

Arrays automatically grow as you add elements.

Swift
1
2
3
shoppingList.append("blue paint")
print(shoppingList)
// ["catfish", "bottle of water", "tulips", "blue paint"]

dictionary

Create a dictionary

Swift
1
2
3
4
5
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
print(occupations)

Add element in dictionary

Swift
1
2
3
4
// ["Kaylee": "Mechanic", "Malcolm": "Captain"]
occupations["Jayne"] = "Public Relations"
print(occupations)
// ["Kaylee": "Mechanic", "Jayne": "Public Relations", "Malcolm": "Captain"]

Empty array or dictionary

To create an empty array or dictionary, use the initializer syntax.

Swift
1
2
let emptyArray = [String]()
let emptyDictionary = [String: Float]()

Infer array or dictionary

If type information can be inferred, you can write an empty array as [] and an empty dictionary as [:]—for example, when you set a new value for a variable or pass an argument to a function.

Swift
1
2
3
4
5
6
7
8
9
10
shoppingList = []
occupations = [:]

shoppingList.append("iPhone")
print(shoppingList)
// "iPhone"]

occupations["Zacks"] = "Data Scientist"
print(occupations)
// ["Zacks": "Data Scientist"]

Swift Data Type


Swift Functions

A function is a block of code which only runs when it is called.

You can pass data, known as parameters, into a function.

A function can return data as a result.


Creating a Function

In Python a function is defined using the def keyword:

Python
1
2
def myFunc():
print("Hello Python!")
Swift
1
2
3
func myFunc() {
print("Hello Swift!")
}

Calling a Function

To call a function, use the function name followed by parenthesis:

Python
1
2
3
4
5
def myFunc():
print("Hello Python!")

myFunc()
# Hello Python
Swift
1
2
3
4
5
6
func myFunc() {
print("Hello Swift!")
}

myFunc()
// Hello Swift!

Arguments

Information(Parameters) can be passed into functions as arguments.

Arguments are specified after the function name, inside the parentheses. You can add as many arguments as you want, just separate them with a comma.

The following example has a function with one argument (name). When the function is called, we pass along a first name, which is used inside the function to print the full name:

Python
1
2
3
4
5
6
7
8
9
10
# A function prints hello name.
def myFunc(name):
print("Hello " + name)

myFunc("Zacks")
# Hello Zacks
myFunc("Amber")
# Hello Amber
myFunc("33")
# Hello 33
Swift
1
2
3
4
5
6
7
8
9
10
11

func myFunc() {
print("Hello " + name)
}

myFunc("Zacks")
// Hello Zacks
myFunc("Amber")
// Hello Amber
myFunc("33")
// Hello 33

Arguments are often shortened to args in Python documentations.


Parameters or Arguments?

The terms parameter and argument can be used for the same thing: information that are passed into a function.

From a function’s perspective:

  • A parameter is the variable listed inside the parentheses in the function definition.
  • An argument is the value that are sent to the function when it is called.

Required Arguments

By default, a function must be called with the correct number of arguments. Meaning that if your function expects 2 arguments, you have to call the function with 2 arguments, not more, and not less.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# A function prints capitalized name
def name(first_name, last_name):
first_name = first_name.capitalize()
last_name = last_name.capitalize()
print("My name is " + first_name + " " + last_name)

name("Zacks", "Shen")
# My name is Zacks Shen

name("zacks", "SHEN")
# My name is Zacks Shen

name("Zacks")
# TypeError: name() missing 1 required positional argument: 'last_name'

Arguments are often shortened to args in Python documentations.
args are positional arguments.


Arbitrary Arguments, *args

If you do not know how many arguments that will be passed into your function, add a * before the parameter name in the function definition.

This way the function will receive a tuple of arguments, and can access the items accordingly:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
# A function prints capitalized name
def _name(*name):
name = list(name) # Remember 'tuple' object does not support item assignment
index = len(name) # Get the length of 'name' argument
for i in range(index):
name[i] = name[i].capitalize()
print("My name is " + name[0] + " " + name[1])

_name("Zacks", "Shen")
# My name is Zacks Shen

_name("zacks", "SHEN")
# My name is Zacks Shen

Arbitrary Arguments are often shortened to *args in Python documentations.
*args are positional arguments.


Keyword Arguments, kwargs

You can also send arguments with the key = value syntax.

This way the order of the arguments does not matter.

Python
1
2
3
4
5
6
7
8
9
# A function prints capitalized name with a title
def name(first_name, last_name, title):
first_name = first_name.capitalize()
last_name = last_name.capitalize()
title = title.upper()
print("I am " + title + " " + first_name + " " + last_name)

name(title = "mr", last_name = "shen", first_name = "ZACKS")
# I am MR Zacks Shen

The phrase Keyword Arguments are often shortened to kwargs in Python documentations.
kwargs are NOT positional arguments.


Arbitrary Keyword Arguments, **kwargs

If you do not know how many keyword arguments that will be passed into your function, add two asterix: ** before the parameter name in the function definition.

This way the function will receive a dictionary of arguments, and can access the items accordingly:

Python
1
2
3
4
5
6
7
8
9
# A function prints capitalized name with a title
def _name(**name):
name["first_name"] = name["first_name"].capitalize()
name["last_name"] = name["last_name"].capitalize()
name["title"] = name["title"].upper()
print("I am {0} {1} {2}".format(name["title"], name["first_name"], name["last_name"]))

_name(title = "mr", last_name = "shen", first_name = "ZACKS")
# I am MR Zacks Shen

Arbitrary Keyword Arguments are often shortened to *kwargs* in Python documentations.
*
kwargs* are NOT positional arguments


Default Parameter Value

If we call the function without argument, it uses the default value:

Python
1
2
3
4
5
6
7
8
9
10
11
12
# A function prints capitalized name with a title and country
def _name(country = "United States", **name): # Remember arg should put before **kwarg
name["first_name"] = name["first_name"].capitalize()
name["last_name"] = name["last_name"].capitalize()
name["title"] = name["title"].upper()
print("I am {0} {1} {2}, and I come from {3}".format(name["title"], name["first_name"], name["last_name"], country))

_name(title = "mr", last_name = "shen", first_name = "ZACKS")
# I am MR Zacks Shen, and I come from United States

_name(title = "mr", last_name = "shen", first_name = "ZACKS", country = "Iceland")
# I am MR Zacks Shen, and I come from Iceland

Keyword-only Arguments

If we use keyword arguments, we cannot restrain what the user input.

Take the example from Default Parameter Value:
This function accept the unexpected parameter (gender).

Python
1
2
3
4
5
6
7
8
9
10
11
12
# A function prints capitalized name with a title and country
def _name(country = "United States", **name): # Remember arg should put before **kwarg
name["first_name"] = name["first_name"].capitalize()
name["last_name"] = name["last_name"].capitalize()
name["title"] = name["title"].upper()
print("I am {0} {1} {2}, and I come from {3}".format(name["title"], name["first_name"], name["last_name"], country))

_name(title = "mr", last_name = "shen", first_name = "ZACKS")
# I am MR Zacks Shen, and I come from United States

_name(title = "mr", last_name = "shen", first_name = "ZACKS", country = "Iceland", gender = "man")
# I am MR Zacks Shen, and I come from Iceland.

We successfully import gener = "man" to the function even it will not be executed. But it is still dangerous.

A keyword-only argument could help us restraining user input.
We can use * to split the arguments. The arguments after * are keyword-only arguments, which could have a default value.

This function prevents from the unexpected parameter (gender).

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# A function prints capitalized name with a title and country
def name(first_name, last_name, *, title, country = "United States"):
first_name = first_name.capitalize()
last_name = last_name.capitalize()
title = title.upper()
print("I am {0} {1} {2}, and I come from {3}".format(title, first_name, last_name, country))

name(title = "mr", last_name = "shen", first_name = "ZACKS")
# I am MR Zacks Shen, and I come from United States

name(title = "mr", last_name = "shen", first_name = "ZACKS", country = "Iceland")
# I am MR Zacks Shen, and I come from Iceland

name(title = "mr", last_name = "shen", first_name = "ZACKS", gender = "Man")
# TypeError: name() got an unexpected keyword argument 'gender'

You can Also use *args to split the arguments:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# A function prints capitalized name with a title and country
def name(first_name, last_name, *base_information, country = "United States"):
first_name = first_name.capitalize()
last_name = last_name.capitalize()
print("I am {0} {1} {2}, a {3}, and I come from {4}".format(base_information[0].upper(), first_name, last_name, base_information[1], country))

name("Zacks", "shen", "mr", "man")
# I am MR Zacks Shen, and I come from United States

name("Zacks", "shen", "mr", "man", country = "Iceland")
# I am MR Zacks Shen, a man, and I come from Iceland

name(last_name = "shen", first_name = "Zacks", "mr", "man", country = "Iceland")
# SyntaxError: positional argument follows keyword argument
# Remember keyword argument must follows positional argument. Because I define last_name = "shen", which means the positional argument has been considered as keyword argument.

Order of Arguments

Warning!!!
Basically, you must define a function in the following way to avoid SyntaxError: positional argument follows keyword argumen:

Python
1
2
def function_name(positional arguments, keyword arguments):
pass

And the detailed order is:

  1. Positional arguments, arg
  2. Default arguments
  3. Arbitrary Arguments, *arg
  4. Keyword-only arguments
  5. Keyword arguments, kwargs
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Notice in this example, country = "United States" is NOT a default argument; it is a Keyword-only arguments since it follows the *arg.
# A function prints capitalized name with a title and country
def name(first_name, last_name, *base_information, country = "United States"):
first_name = first_name.capitalize()
last_name = last_name.capitalize()
print("I am {0} {1} {2}, a {3}, and I come from {4}".format(base_information[0].upper(), first_name, last_name, base_information[1], country))

name("Zacks", "shen", "mr", "man")
# I am MR Zacks Shen, and I come from United States

name("Zacks", "shen", "mr", "man", country = "Iceland")
# I am MR Zacks Shen, a man, and I come from Iceland

name(last_name = "shen", first_name = "Zacks", "mr", "man", country = "Iceland")
# SyntaxError: positional argument follows keyword argument
# Remember keyword argument must follows positional argument. Because I define last_name = "shen", which means the positional argument has been considered as keyword argument.

Return Values

To let a function return a value, use the return statement:

Python
1
2
3
4
5
6
# A function returns your bmi
def bmi_calculate(h, w):
return w/(h*h)

bmi_calculate(1.8, 70)
# 21.604938271604937

Return is one of the most important concepts! A deep learning could help us understand it

Here is a for statement to print a series numbers in a range:

Python
1
2
3
4
5
6
7
for i in range(3):
print(i)
"""
0
1
2
"""

Let’s do the same thing in a function, then call it:

Python
1
2
3
4
5
6
7
8
9
10
11
# A function prints the values in a range one by one.
def tmp():
for i in range(3):
print(i)

tmp()
"""
0
1
2
"""

You may understand that sometimes print() and return() all print the result on your screen:

Python
1
2
3
4
5
6
# A function RETURNS your bmi
def bmi_calculate_1(h, w):
return w/(h*h)

bmi_calculate_1(1.8, 70)
# 21.604938271604937
Python
1
2
3
4
5
6
# A function PRINTS your bmi
def bmi_calculate_2(h, w):
print(w/(h*h))

bmi_calculate_2(1.8, 70)
# 21.604938271604937

However, if try to do the same thing in return.

Python
1
2
3
4
5
6
7
8
9
10
11
# A function PRINTS the values in a range one by one.
def tmp_1():
for i in range(3):
print(i)

tmp_1()
"""
0
1
2
"""
Python
1
2
3
4
5
6
7
8
9
# A function try to RETURN the values in a range one by one, but it doesn't work.
def tmp_2():
for i in range(3):
return(i)

tmp_2()
"""
0
"""

This is weird, right? Why the function only print 0 on the screen? Because return only runs once in a function! And everything after return will be ignored!

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def hello_1():
print("Hello")
print("World")

hello_1()
# Hello
# World

def hello_2():
return("Hello")
return("World") # Will be ignored!

hello_2()
# 'Hello'

def hello_3():
return("Hello")
print("World") # Will be ignored!

hello_3()
# 'Hello'

def hello_4():
print("Hello")
return("World") # Will not be ignored!

hello_4()
# Hello
# 'World'

From the official definition:
return may only occur syntactically nested in a function definition, not within a nested class definition.

If an expression list is present, it is evaluated, else None is substituted.

return leaves the current function call with the expression list (or None) as return value.

When return passes control out of a try statement with a finally clause, that finally clause is executed before really leaving the function.


The pass Statement

function definitions cannot be empty, but if you for some reason have a function definition with no content, put in the pass statement to avoid getting an error.

Python
1
2
3
4
5
def my_function():
# SyntaxError: unexpected EOF while parsing

def my_function():
pass

Recursion

Python also accepts function recursion, which means a defined function can call itself.

Recursion is a common mathematical and programming concept. It means that a function calls itself. This has the benefit of meaning that you can loop through data to reach a result.

The developer should be very careful with recursion as it can be quite easy to slip into writing a function which never terminates, or one that uses excess amounts of memory or processor power. However, when written correctly recursion can be a very efficient and mathematically-elegant approach to programming.

To a new developer it can take some time to work out how exactly this works, best way to find out is by testing and modifying it.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# A function returns exponentiation
def exp(b, n):
if n > 0:
return b * exp(b, n - 1)
else:
return 1
# when n = 0, function returns exp(b, 0) -> 1
# when n = 1, function returns b * exp(b, n - 1) -> b * 1
# when n = 2, function returns b * exp(b , n - 1) * exp(b , n - 2) -> b * b * 1

exp(2, 0)
# 1

exp(2, 1)
# 2

exp(2, 10)
# 1024

A program to calculate Fibonacci numbers

In mathematics, the Fibonacci numbers, commonly denoted Fn, form a sequence, called the Fibonacci sequence, such that each number is the sum of the two preceding ones, starting from 0 and 1. That is,

$${\displaystyle F_{0}=0,\quad F_{1}=1,}$$
and

$${\displaystyle F_{n}=F_{n-1}+F_{n-2},}$$
for $n > 1$.

The beginning of the sequence is thus:

$${\displaystyle 0,;1,;1,;2,;3,;5,;8,;13,;21,;34,;55,;89,;144,;\ldots }{\displaystyle 0,;1,;1,;2,;3,;5,;8,;13,;21,;34,;55,;89,;144,;\ldots }$$

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# A function returns Fibonacci number
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)

fib(6)
# 8

fib(12)
# 144

A program for Exponential operation

In Python, you can execute Exponential operation in a easy way:

Python
1
2
3
4
5
def exp(x, n):
result = 1
for i in range(n):
result *= x
return result

Swift Operators

Operators are used to perform operations on variables and values.

Python divides the operators in the following groups:

  • Arithmetic operators
  • Assignment operators
  • Comparison operators
  • Logical operators
  • Identity operators
  • Membership operators
  • Bitwise operators

Swift Arithmetic Operators

Arithmetic operators are used with numeric values to perform common mathematical operations.

Operator Name
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus
** Exponentiation
// Floor division

Swift Assignment Operators

Assignment operators are used to assign values to variables:

Operator Example Same As
= x = 5 x = 5
+= x += 3 x = x + 3
-= x -= 3 x = x - 3
*= x *= 3 x = x * 3
/= x /= 3 x = x / 3
%= x %= 3 x = x % 3
//= x //= 3 x = x // 3
**= x **= 3 x = x ** 3
&= x &= 3 x = x & 3
|= x |= 3 x = x | 3
^= x ^= 3 x = x ^ 3
>>= x >>= 3 x = x >> 3
<<= x <<= 3 x = x << 3

Swift Comparison Operators

Comparison operators are used to compare two values.

Operator Name
== Equal
!= Not equal
> Greater than
< Less than
>= Greater than or equal to
<= Less than or equal to

Swift Logical Operators

Logical operators are used to combine conditional statements.

Operator Description Example
&& Returns True if both statements are true x < 5 && x < 10
|| Returns True if one of the statements is true x < 5 or x < 4
! Reverse the result, returns False if the result is true not(x < 5 and x < 10)

Python Identity Operators

Identity operators are used to compare the objects, not if they are equal, but if they are actually the same object, with the same memory location.

Operator Description Example
is Returns true if both variables are the same object x is y
is not Returns true if both variables are not the same object x is not y

Python Membership Operators

Membership operators are used to test if a sequence is presented in an object.

Operator Description Example
in Returns True if a sequence with the specified value is present in the object x in y
not in Returns True if a sequence with the specified value is not present in the object x not in y

Python Bitwise Operators

Bitwise operators are used to compare (binary) numbers.

Operator Name Description
& AND Sets each bit to 1 if both bits are 1
^ XOR Sets each bit to 1 if only one of two bits is 1
~ NOT Inverts all the bits
<< Zero fill left shift Shift left by pushing zeros in from the right and let the leftmost bits fall off
>> Signed right shift Shift right by pushing copies of the leftmost bit in from the left, and let the rightmost bits fall off
| OR Sets each bit to 1 if one of two bits is 1