Swift Associated Values in Depth
Associated values let each enum case carry data in its own shape. A pattern binds that data to a name when a stored value is matched.
Binding one case with if case
The if case pattern matches only the found case and binds its index. The second value holds a different case, so its check takes the else branch.
enum SearchOutcome {
case found(index: Int)
case notFound
case failed(message: String)
}
let outcome = SearchOutcome.found(index: 4)
if case .found(let index) = outcome {
print("Found at \(index)")
} else {
print("Not found")
}
let other = SearchOutcome.notFound
if case .found(let index) = other {
print("Found at \(index)")
} else {
print("Not found")
}A switch binding different shapes
Each branch binds the payload shape of its own case. The found case gives an Int, the failed case gives a String, and the notFound case gives nothing.
enum SearchOutcome {
case found(index: Int)
case notFound
case failed(message: String)
}
func describe(outcome: SearchOutcome) -> String {
switch outcome {
case .found(let index):
return "Found at \(index)"
case .notFound:
return "No match"
case .failed(let message):
return "Failed with \(message)"
}
}
print(describe(outcome: .found(index: 2)))
print(describe(outcome: .notFound))
print(describe(outcome: .failed(message: "Offline")))A method reading its own payload
The summary method switches over the value it was called on. Each branch reads the payload stored in that value.
enum Delivery {
case pickup(code: Int)
case shipped(tracking: String)
case cancelled
func summary() -> String {
switch self {
case .pickup(let code):
return "Pickup code \(code)"
case .shipped(let tracking):
return "Tracking \(tracking)"
case .cancelled:
return "Cancelled"
}
}
}
print(Delivery.pickup(code: 81).summary())
print(Delivery.shipped(tracking: "TRK9").summary())
print(Delivery.cancelled.summary())Example
enum Response {
case success(Int)
case failure(String)
}
let response = Response.success(200)
print(response)
if case .success(let code) = response {
print(code)
}Key points
- Each case of an enum can carry a different number and type of associated values.
- A switch pattern binds the payload of the matching case to a local name.
- An if case pattern tests one case and binds its payload in a single check.
- A case with no payload binds nothing in a pattern.
- A method on an enum can switch over its own value and read the payload it holds.
In this example, the response holds the success case carrying 200, and the first print shows success(200). The if case pattern then binds that same number to code, and the second print shows 200 on its own.
Note
A name bound in one branch exists only inside that branch.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does the pattern if case .failed(let reason) = outcome do?