# Swift 5.3 - Section 1: Swift Basics

For this series of posts I have used extensively the book Swift Apprentice by Ray Wenderlich.

I strongly suggest this book, because if you buy the digital copy, Ray Wenderlich guarantees updates for the rest of the life!

I have also to say that Ray Wenderlich offers a cheat sheet available for download for free.

The purpose of these post is not to copy the book itself, that I strongly suggest to read, also doing the suggested exercises, that give the required confidence to really learn the language.

In particular I will not explain how to use Xcode or the playgrounds. The idea is that you buy the book and read it!

Final note: my background is deep experience in C#, so maybe some concepts are obvious for me. If you read this article, find it useful, but would like that I add something, don't hesitate to comment here below! But remember, my goal is not to copy the book :-)

# Chapter 1: Expressions, Variables & Constants

## Code comments

Swift allows single line comments, multi line comments and also nested comments:

```
// This is a comment. It is not executed.
/* This is also a comment.
Over many..
many...
many lines. */
```

Nested comments are supported:

```
/* This is a comment.
/* And inside it
is
another comment.
*/
Back to the first.
*/
```

## Print in the debug area

```
print("Hello, Swift Apprentice reader!")
```

How to remove the new-line at the end, or how to finish the current line:

```
print("\(player), ", terminator: "") // no newline
print("") // print one final newline
```

## The remainder operation

Between ints:

```
28 % 10
```

Between decimal numbers:

```
(28.0).truncatingRemainder(dividingBy: 10.0)
```

## Some math functions

```
max(5, 10)
// 10
min(-5, -10)
// -10
sin(45 * Double.pi / 180)
// 0.7071067811865475
cos(135 * Double.pi / 180)
// -0.7071067811865475
(2.0).squareRoot()
// 1.414213562373095
Int.random(in: 1...6)
```

## Constants and variables

```
let number: Int = 10
var variableNumber: Int = 42
```

Variables are block-scoped.

# Chapter 2: Types & Operations

## Type conversion

```
var integer: Int = 100
var decimal: Double = 12.5
integer = Int(decimal)
```

## Type inference

In Xcode, you can analyze the type of a variable or constant with Option+Click on the name itself.

How to cast with type inference:

```
let actuallyDouble: Double = 3
let actuallyDouble: Double(3)
let actuallyDouble = 3 as Double
```

## Characters and strings

```
let characterA: Character = "a"
let stringDog = "Dog" // Inferred to be of type String
```

Interpolation:

```
message = "Hello my name is \(name)!" // "Hello my name is Matt!"
```

Multi-line strings:

```
let bigString = """
You can have a string
that contains multiple
lines
by
doing this.
"""
print(bigString)
```

## Tuples

```
let coordinates: (Int, Int) = (2, 3)
let x1 = coordinates.0
let y1 = coordinates.1
```

Named tuples:

```
let coordinatesNamed = (x: 2, y: 3)
// Inferred to be of type (x: Int, y: Int)
let x2 = coordinatesNamed.x
let y2 = coordinatesNamed.y
```

Deconstruction:

```
let coordinates3D = (x: 2, y: 3, z: 1)
let (x3, y3, z3) = coordinates3D
let (x4, y4, _) = coordinates3D
```

## Type aliases

```
typealias Animal = String
let myPet: Animal = "Dog"
typealias Coordinates = (Int, Int)
let xy: Coordinates = (2, 4)
```

# Chapter 3: Basic Control Flow

## Bool toggling

```
var switchState = true
switchState.toggle() // switchState = false
switchState.toggle() // switchState = true
```

## If statement

```
let hourOfDay = 12
var timeOfDay = ""
if hourOfDay < 6 {
timeOfDay = "Early morning"
} else if hourOfDay < 12 {
timeOfDay = "Morning"
} else if hourOfDay < 17 {
timeOfDay = "Afternoon"
} else if hourOfDay < 20 {
timeOfDay = "Evening"
} else if hourOfDay < 24 {
timeOfDay = "Late evening"
} else {
timeOfDay = "INVALID HOUR!"
}
print(timeOfDay)
```

AND and OR conditions are short-circuited.

## While loops

```
var sum = 1
while sum < 1000 {
sum = sum + (sum + 1)
}
```

## Repeat While loops

```
sum = 1
repeat {
sum = sum + (sum + 1)
} while sum < 1000
```

# Chapter 4: Advanced Control Flow

## Countable ranges

```
let closedRange = 0...5
let halfOpenRange = 0..<5
```

## For loops

```
let count = 10
var sum = 0
for i in 1...count {
sum += i
}
```

Conditions in loops:

```
sum = 0
for i in 1...count where i % 2 == 1 {
sum += i
}
```

## Continue to an outer loop

```
sum = 0
rowLoop: for row in 0..<8 {
columnLoop: for column in 0..<8 {
if row == column {
continue rowLoop
}
sum += row * column
}
}
```

## Switch statements

```
switch hourOfDay {
case 0...5:
timeOfDay = "Early morning"
case 6...11:
timeOfDay = "Morning"
case 12...16:
timeOfDay = "Afternoon"
case 17...19:
timeOfDay = "Evening"
case 20..<24:
timeOfDay = "Late evening"
default: timeOfDay = "INVALID HOUR!"
}
```

Condition on cases:

```
switch number {
case let x where x % 2 == 0:
print("Even")
default:
print("Odd")
}
```

Pattern matching:

```
let coordinates = (x: 3, y: 2, z: 5)
switch coordinates {
case (0, 0, 0): // 1
print("Origin")
case (_, 0, 0): // 2
print("On the x-axis.")
case (0, _, 0): // 3
print("On the y-axis.")
case (0, 0, _): // 4
print("On the z-axis.")
default: // 5
print("Somewhere in space")
}
```

Pattern matching when capturing variables:

```
switch coordinates {
case (0, 0, 0):
print("Origin")
case (let x, 0, 0):
print("On the x-axis at x = \(x)")
case (0, let y, 0):
print("On the y-axis at y = \(y)")
case (0, 0, let z):
print("On the z-axis at z = \(z)")
case let (x, y, z):
print("Somewhere in space at x = \(x), y = \(y), z = \(z)")
}
```

More complex example:

```
switch coordinates {
case let (x, y, _) where y == x:
print("Along the y = x line.")
case let (x, y, _) where y == x * x:
print("Along the y = x^2 line.")
default:
break
}
```

# Chapter 5: Functions

## External names

Renaming an external name of a parameter:

```
func printMultipleOf(multiplier: Int, and value: Int) {
print("\(multiplier) * \(value) = \(multiplier * value)")
}
printMultipleOf(multiplier: 4, and: 2)
```

Hiding an external name of a parameter:

```
func printMultipleOf(_ multiplier: Int, and value: Int) {
print("\(multiplier) * \(value) = \(multiplier * value)")
}
printMultipleOf(4, and: 2)
```

Functions support default values.

## Return values

Return values:

```
func multiply(_ number: Int, by multiplier: Int) -> Int {
return number * multiplier
}
let result = multiply(4, by: 2)
```

Return value with a tuple:

```
func multiplyAndDivide(_ number: Int, by factor: Int)
-> (product: Int, quotient: Int) {
return (number * factor, number / factor)
}
let results = multiplyAndDivide(4, by: 2)
let product = results.product
let quotient = results.quotient
```

Removing the return value for single statement functions:

```
func multiply(_ number: Int, by multiplier: Int) -> Int {
number * multiplier
}
func multiplyAndDivide(_ number: Int, by factor: Int)
-> (product: Int, quotient: Int) {
(number * factor, number / factor)
}
```

## Variadic parameters

```
func getHighestGrade(for grades: Int...) -> Int {
grades.max() ?? 0
}
getHighestGrade() // 0
getHighestGrade(3, 7, 5) // 7
```

## Parameters passed by reference

```
func incrementAndPrint(_ value: inout Int) {
value += 1
print(value)
}
var count = 0
incrementAndPrint(&count)
```

## Overloading

```
func printMultipleOf(multiplier: Int, andValue: Int)
func printMultipleOf(multiplier: Int, and value: Int)
func printMultipleOf(_ multiplier: Int, and value: Int)
func printMultipleOf(_ multiplier: Int, _ value: Int)
```

## Functions as variables

Note that when passing a function as variable, the parameter names are not considered in the function signature.

```
func add(a: Int, b: Int) -> Int {
a + b
}
var function = add
function(4, 2)
```

Passing a function as a parameter to another function:

```
func printResult(_ function: (Int, Int) -> Int, _ a: Int, _ b: Int) {
let result = function(a, b)
print(result)
}
printResult(add, 4, 2)
```

## No return

```
func noReturn() -> Never {
}
```

## Commenting your functions

You can automatically comment a function in Xcode with Option-Command-/.

Sample of function declaration:

```
/// Calculates the average of three values
/// - Parameters:
/// - a: The first value.
/// - b: The second value.
/// - c: The third value.
/// - Returns: The average of the three values.
func calculateAverage(of a: Double, and b: Double, and c: Double) -> Double {
let total = a + b + c
let average = total / 3
return average
}
calculateAverage(of: 1, and: 3, and: 5)
```

## Closures

A closure is an anonymous method without parameter names.

A closure always require the return type, even if it is *Void*.

```
typealias Operate = (Int, Int) -> Int
let op: Operate = +
var addClosure: Operate = { (a: Int, b: Int) -> Int in
return a + b
}
```

Shortening closure syntax:

```
let longClosure = { (a: Int, b: Int) -> Int in
a * b
}
let noParameterTypes: Operate = { (a, b) -> Int in
a * b
}
let noReturnType: Operate = { (a, b) in
a * b
}
let shortClosure: Operate = { $0 * $1 }
```

Closures with Void return type:

```
let voidClosure: () -> Void = { () -> Void in
print("Test")
}
let voidClosure: () -> Void = {
print("Test")
}
```

# Chapter 6: Optionals

## Optionals

```
var errorCode: Int?
errorCode = 100
errorCode = nil
```

## Unwrapping

Force unwrapping:

```
var authorName: String? = "Matt Galloway"
var unwrappedAuthorName = authorName!
print("Author is \(unwrappedAuthorName)")
```

Optional binding (plus shadowing, because the unwrapped variable name is the same as the optional name):

```
if let authorName = authorName {
print("Author is \(authorName)")
} else {
print("No author.")
}
```

Multiple optional bindings (all the optionals must be not nil to enter the if statement):

```
if let authorName = authorName,
let authorAge = authorAge {
print("The author is \(authorName) who is \(authorAge) years old.")
} else {
print("No author or no age.")
}
```

Combine multiple unwrapping with additional boolean checks:

```
if let authorName = authorName,
let authorAge = authorAge,
authorAge >= 40 {
print("The author is \(authorName) who is \(authorAge) years old.")
} else {
print("No author or no age or age less than 40.")
}
```

## Introducing guard

Check of input parameters of functions (with guard, you have always to provide an else clause):

```
func guardMyCastle(name: String?) {
guard let castleName = name else {
print("No castle!")
return
}
// At this point, `castleName` is a non-optional String
print("Your castle called \(castleName) was guarded!")
}
```

Example of another use:

```
func maybePrintSides(shape: String) {
guard let sides = calculateNumberOfSides(shape: shape) else {
print("I don’t know the number of sides for \(shape).")
return
}
print("A \(shape) has \(sides) sides.")
}
```

## Nil coalescing

```
var optionalInt: Int? = 10
var mustHaveResult = optionalInt ?? 0
```