๐ŸŽ“ A1Learner
๐Ÿ”
0 of 36 lessons completed

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?