Enums with payloads model states and results precisely and let the compiler check every case is handled.
An enum defines a closed set of cases: enum Direction { case north, south, east, west }. When the type is known you can drop it: let d: Direction = .north.
Enums can have raw values of a single type: enum Planet: Int { case mercury = 1, venus } (venus gets 2). Planet(rawValue: 3) returns an optional, since the number may not match a case. String raw values default to the case name. Add CaseIterable to get allCases.
More powerful are associated values: each case carries its own payload, of any type.
enum Payment {
case cash
case card(last4: String)
case transfer(iban: String, amount: Double)
}You extract payloads in a switch with case .card(let last4) or case let .transfer(iban, amount). Because switch is exhaustive, adding a new case makes the compiler point at every place that must handle it — a big reason to model state with enums rather than flags.
Enums can have computed properties, methods (mutating to change self) and conform to protocols. if case .card(let n) = payment { } tests a single case. indirect allows recursive enums such as expression trees.
Optional and Result are themselves enums with associated values.
Example
enum LoadState {
case idle
case loading(progress: Double)
case loaded([String])
case failed(message: String)
var isBusy: Bool {
if case .loading = self { return true }
return false
}
}
func render(_ s: LoadState) -> String {
switch s {
case .idle: return "Tap to load"
case .loading(let p): return "Loading \(Int(p * 100))%"
case .loaded(let rows) where rows.isEmpty: return "Nothing here"
case .loaded(let rows): return "\(rows.count) rows"
case .failed(let message): return "Error: \(message)"
}
}
print(render(.loading(progress: 0.4))) // Loading 40%
print(render(.loaded(["a", "b"]))) // 2 rows
print(LoadState.idle.isBusy) // falseRemember
- Associated values attach different data to each case
switchover an enum must be exhaustive — the compiler finds missing cases- Raw-value init
Enum(rawValue:)is failable
Watch out for
- Adding
default:to every enum switch, which hides new cases from the compiler.