Skip to content
Theory · Conditions · lesson 3 of 5

switch

Picture a sorting machine at a post office. A parcel rides along a belt, the machine reads the number on its label and drops the parcel into one of several chutes. Above each chute hangs a sign: which numbers go there. The last chute is marked "everything else". The machine is not switched on until every number has a chute.

The else if chain from the previous lesson also sorts values into branches, but each branch compares the same value all over again. The switch statement works like the sorting machine: it takes the value once and runs the case branch with the matching sign:

SWIFT
let minutes = 450
let hour = minutes / 60
switch hour {
case 6, 7, 8:
    print("breakfast") // breakfast
case 12, 13:
    print("lunch")
case 18, 19, 20:
    print("dinner")
default:
    print("snack")
}

Let's walk through the program:

  1. hour gets 450 / 60. Dividing whole numbers drops the remainder, so hour is 7: 450 minutes after midnight is 7:30.
  2. switch hour takes the value 7 and checks it against the branches from top to bottom.
  3. case 6, 7, 8: — seven is in the list, so the program prints breakfast.
  4. The program skips the remaining branches, default included.

case branches

A branch starts with the word case, followed by its sign and a colon. The branch's code goes under the colon and needs no braces. This lesson covers two kinds of signs.

Several values

Values are listed with commas: case 6, 7, 8:. The branch runs if the value equals any of them. The values have the same type as the expression after switch, here Int.

A range

Instead of a long list, you can write a range with ... or ..<:

SWIFT
switch hour {
case 6...9:
    print("breakfast") // breakfast
case 12...14:
    print("lunch")
case 18...21:
    print("dinner")
default:
    print("snack")
}

The branch case 6...9: runs for any hour from 6 to 9 inclusive. Values and ranges can be mixed even within one branch: case 0, 22...23:.

default and an exhaustive switch

The default branch runs when no case fits. It is the "everything else" chute.

In Swift a switch must be exhaustive: every possible value must have a branch. The compiler checks this before the program runs, and it checks the type, not the current value. It does not check whether Int values and ranges cover every number, so branches with them never count as complete—not even case Int.min...Int.max:. That is why a switch on a number almost always ends with a default branch, and without one it does not compile:

SWIFT
switch hour { // ✗
case 6...9:
    print("breakfast")
case 12...14:
    print("lunch")
}
TEXT
error: switch must be exhaustive

Under the error line, the compiler prints the hint add a default clause, which means "add a default branch".

Only the first matching branch

The machine drops a parcel into the first chute that fits and moves straight on to the next parcel. A switch does the same: it checks the branches from top to bottom, runs the first one that fits and stops there. It does not check the branches below.

Here the post-office picture is not exact. At a real post office a number has exactly one chute, while ranges in a switch can overlap, and then the order of the branches decides. In the program below, the age 15 fits both 7...17 and 15...25. Press "Next step" and watch where the program goes after it prints child:

LiveWhich branch runsstep 1 of 8 · frames: 1

The constant year gets the value 2026.

Watch the highlighted line after child is printed

After the case 7...17 branch, the program goes straight to the line after the switch. The branch 15...25 does not run, even though 15 is in it. The compiler does not forbid such overlaps, so the order of the branches is your choice.

In C and languages like it, execution at the end of a branch falls through into the next one unless you write break. Swift has no such thing: a branch ends on its own, and no break is needed at its end.

Interviewers like to ask this: how does a switch in Swift differ from one in C? A good answer names three differences:

  • a branch does not fall through into the next one, and no break is needed at its end;
  • a switch is exhaustive: without a branch for every possible value it does not compile;
  • one case can list several values or hold a range.

Common mistake

The program has nothing to do at night, so the branch for the hours 0...5 was left empty:

SWIFT
switch hour {
case 0...5: // ✗
case 6...9:
    print("breakfast")
default:
    print("snack")
}
TEXT
error: 'case' label in a 'switch' must have at least one executable statement

In Swift a branch cannot be empty: it needs at least one statement. To make a branch do nothing, you write break in it: this statement ends the switch at once. The result is case 0...5: break.

Key points

  • A switch takes the value once and runs the first case branch it fits: by a list of values or by a range.
  • After a branch the switch ends on its own: execution does not fall into the next branch, and no break is needed.
  • A switch is exhaustive: the compiler does not check whether Int values and ranges cover every number, so without default such a switch does not compile.
  • An empty branch does not compile; a branch that does nothing is written with break.