Enumerations
An enumeration defines a common type for a group of related values, letting you work with them in a type-safe way. Swift enums are first-class types: they can have methods, computed properties, initializers, and conform to protocols. They're far more powerful than the integer-only enums in many other languages.
Enumeration syntax
Introduce an enum with the enum keyword and list its
cases with case. Each case is a fully fledged
value of the enum's type — it isn't backed by an integer unless you ask.
enum CompassPoint {
case north
case south
case east
case west
}
// Multiple cases on one line are also allowed:
enum Planet {
case mercury, venus, earth, mars
}
var direction = CompassPoint.north
direction = .south // type already known → dot shorthand
Each enum defines a brand-new type with its own set of values.
Matching enum values with switch
A switch statement is the natural way to branch on an enum. The
switch must be exhaustive: cover every case, or include a
default. This exhaustiveness check is one of the biggest safety
wins of Swift enums.
switch direction {
case .north:
print("Lots of planets have a north")
case .south:
print("Watch out for penguins")
case .east:
print("Where the sun rises")
case .west:
print("Where the skies are blue")
}
// → Watch out for penguins
Iterating over cases
Conform an enum to CaseIterable and Swift synthesizes an
allCases collection containing every case in declaration order.
enum Beverage: CaseIterable {
case coffee, tea, juice
}
print("\(Beverage.allCases.count) beverages available")
// → 3 beverages available
for drink in Beverage.allCases {
print(drink)
}
// → coffee / tea / juice
Associated values
A case can store associated values of any type alongside it. Different cases can carry different kinds of data. This makes enums a superb tool for modeling state where each state needs its own payload.
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
var product = Barcode.upc(8, 85909, 51226, 3)
product = .qrCode("ABCDEFGHIJKLMNOP")
switch product {
case .upc(let system, let manufacturer, let product, let check):
print("UPC: \(system), \(manufacturer), \(product), \(check)")
case .qrCode(let code):
print("QR code: \(code)")
}
// → QR code: ABCDEFGHIJKLMNOP
Tip: when all the bindings in a case are constants you
can write a single let before the case name, e.g.
case let .qrCode(code):.
Raw values
As an alternative to associated values, you can give every case a prefilled raw value of the same underlying type — a string, character, or any integer or floating-point number. Declare the raw type after the enum's name.
enum ASCIIControl: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}
Implicitly assigned raw values
For Int and String raw types Swift can assign the
values for you. Integers auto-increment from the previous case (or from 0),
and strings default to the case name.
enum Planet: Int {
case mercury = 1, venus, earth, mars // venus = 2, earth = 3, mars = 4
}
enum CompassPoint: String {
case north, south, east, west // raw values are "north", "south", …
}
print(Planet.earth.rawValue) // → 3
print(CompassPoint.west.rawValue) // → west
Initializing from a raw value
Enums with a raw type get a failable initializer
init?(rawValue:) automatically. It returns an optional because
the raw value might not match any case.
let possiblePlanet = Planet(rawValue: 3) // Planet? → .earth
if let planet = Planet(rawValue: 9) {
print("Found \(planet)")
} else {
print("There is no planet 9") // → There is no planet 9
}
Recursive enumerations
A recursive enumeration has cases whose associated values
are themselves instances of the enum. Mark such cases — or the whole enum —
with indirect so Swift can store them via an extra level of
indirection. This is ideal for tree-shaped data like expressions.
indirect enum Expr {
case number(Int)
case addition(Expr, Expr)
case multiplication(Expr, Expr)
}
func evaluate(_ expr: Expr) -> Int {
switch expr {
case .number(let value):
return value
case .addition(let l, let r):
return evaluate(l) + evaluate(r)
case .multiplication(let l, let r):
return evaluate(l) * evaluate(r)
}
}
// (5 + 4) * 2
let tree = Expr.multiplication(.addition(.number(5), .number(4)), .number(2))
print(evaluate(tree)) // → 18
Note: writing indirect before a single
case applies it to just that case, while writing it before the
enum keyword applies it to every case that needs it.
Recap
Swift enumerations model a fixed set of possibilities with full type safety.
You can pattern-match them with exhaustive switch, iterate them
with CaseIterable, attach per-case payloads via associated
values, map them to/from a backing type with raw values, and even build
recursive data structures with indirect.