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.