Vocabulary for this course

The terms the chapters assume, in plain words. You can open this from any chapter.

array
An ordered list of values of one type, reached by position starting at zero.
block
A group of lines of code that run together, often inside curly brackets.
closure
A piece of code you can store in a value and pass to other code, remembered with the names around it.
compiler
The program that turns the code you write into something the machine can run, reporting mistakes before it does.
dictionary
A collection of key and value pairs, where each key appears once and finds its value.
enum
A type whose value is one of a fixed set of named cases, which may each carry extra data.
expression
A piece of code that produces a value, such as a sum or a call to a function.
function
A named piece of code that takes values and returns a result when called.
guard
A check that must pass before the code after it runs, leaving the scope early when it fails.
method
A function that belongs to a type and is called on a value of that type.
nil
The absence of a value, allowed only where a type says a value may be missing.
operator
A symbol such as plus or equals that combines values into a new one.
optional
A type that either holds a value or holds nothing, written with a question mark after the type.
optional chaining
Writing a question mark before something you reach into, so the result is nil when the value is missing.
property
A named value that belongs to a type or to one of its values.
protocol
A list of requirements that a type promises to meet, so code can work with any type that meets them.
scope
The region of code where a name can be used before it goes out of reach.
string interpolation
Putting a value inside text with a backslash and parentheses, so the value becomes part of the text.
struct
A type that groups related values and makes a copy whenever it is given another name or passed along.
subscript
A way to read or write an item in an array or dictionary by putting a key or position in square brackets.
type
What kind of value something is, such as a whole number or text, and what it can do.
unwrap
To get the value out of an optional after checking that something is there.

Swift from the ground up

Decisions with if and switch

Choosing a path with if and else, sorting many answers with switch, and matching ranges of numbers.

Part 4 of 12

Beginner15 min readBack to Courses

Asking a question

An if runs a block only when a condition is true. The condition is a question with a Bool answer, such as score >= 80. Brackets around the condition are not needed, but the curly braces around the block are required.

Add an else for the other case. A chain of else if checks answers in order, and the first true one wins, so the order of the questions is part of your meaning.

Order decides the answer. A score of 85 tested against >= 90 first falls through to >= 80 and prints grade B. Put >= 70 above >= 80 and the same score prints grade C, because the first true branch wins and the rest are never asked. When a chain gives a surprising grade, read the conditions from the top and stop at the first one that is true.

switch, when there are many answers

A switch compares one value against several case labels. Each case ends where the next begins, so there is no fall-through and no break to remember.

The cases must cover every possibility. For a whole number that means a default, and for an enum that means every case, which the compiler checks for you.

A switch works on strings and characters as well as numbers. case "north", "south": lists two values in one arm, and the comparison is exact, including case. There is no fall-through from one case to the next, so an arm ends when its block ends; fallthrough exists but is rare, and reaching for it usually means the cases should be combined.

Matching ranges and a quick choice

A case can be a range, so case 1...5 matches any number from one to five. This reads closer to the way you would say it out loud than a pile of comparisons.

The short form, question ? a : b, picks between two values in one line. Use it for small choices, and reach for if when the branches do real work.

A range can be open at one end. case ..<0: catches every negative number and case 100...: catches everything from one hundred upward, which is how a switch covers a number line without listing values. A where clause adds a condition to a case: case let n where n % 2 == 0: matches only the even values that reached that arm.

Every condition is a Bool

Swift has no notion of a truthy number or a truthy string. The thing between if and the opening brace must be a Bool, and a comparison is the usual way to make one. if count is an error; if count > 0 says what you mean.

The operators && and || stop as soon as the answer is known. That short-circuit is why if index < items.count && items[index] > 0 is safe: when the first test is false, the second one never runs.

The same short-circuit makes a guard against nil safe: check for nil first, then use the value.

Short-circuiting is not just an optimisation; it is part of the meaning. if user != nil && user!.age >= 18 is safe because the second test is never reached when the first is false. Swap the two tests and the same line can crash. Whenever one condition protects another, the protecting test belongs on the left.

The ! operator reverses a Bool, so if !items.isEmpty reads as “if there are items”. It binds tightly, so !a && b means (!a) && b. A double negation is legal and almost always a sign that the condition should be rewritten in the positive.

Two ways to branch

let score = 82

if score >= 90 {
    print("grade A")
} else if score >= 80 {
    print("grade B")
} else {
    print("keep going")
}

switch score {
case 90...100:
    print("top band")
case 80..<90:
    print("middle band")
default:
    print("low band")
}

Three mistakes decide the wrong branch. A condition must be a Bool, so if score will not compile. A single = assigns and is not allowed in a condition, while == compares. A switch over a number needs a default unless the cases cover every value, and the first matching case wins, so put narrow ranges before wide ones.

A grade, a day and a size

Run it and read which branch each value took. Then change the score so a different grade prints, and predict the output before you run it again.

Output
Click "Run" to execute your code

Try these next

  • Write a grade chain for five bands and test a score at each boundary.
  • Replace an if chain with a switch and check that every band still prints the same word.
  • Use a ternary to choose between two labels, then rewrite it as an if and compare which reads better.

A ticket price for one visitor

Run it, then change the age and the member flag. Predict the price and the message before each run, and check which branch produced them.

Output
Click "Run" to execute your code

A switch must be able to finish. If you leave out a default, the compiler will complain when the cases cannot cover every value, which is its way of asking what should happen next.

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

With a chain of else if, which branch runs?