# Swift Enums: Associated Values vs Raw Values Explained

Source: https://devdocs10.com/articles/swift/swift-enums-associated-vs-raw  
By Murat Bo · Published 2026-05-22 · DevDocs10 (https://devdocs10.com)

Swift enums can do much more than just list named cases. Two of the most important enum features are raw values and associated values, and understanding the difference helps you model data correctly, write safer code, and avoid common compiler errors. In this article, you will learn what each feature does, how they differ, when to use each one, and how to apply them in realistic Swift 5+ code.

> **Quick answer:** Use raw values when each enum case maps to one fixed underlying value such as a string or integer. Use associated values when each case needs to carry extra data that can vary at runtime, such as an ID, message, or coordinates.

> **Difficulty:** Beginner
>
> **Helpful to know first:** You will understand this better if you already know basic Swift syntax, how enums work at a simple level, and how `switch` statements match enum cases.

## 1. What Are the Options?

Swift enums support two different ways to attach meaning to cases: raw values and associated values. They solve different problems, even though beginners often confuse them.

- **Raw values** give every case one predefined value of the same type.
- **Associated values** let a case store extra data that can be different each time you create that case.
- Raw values are fixed as part of the enum definition.
- Associated values are provided when you create an enum value.
- An enum can use associated values or raw values, but a single case does not use both as the same mechanism.

For example, a traffic light enum is a good fit for raw values because each case can map to a stable string like `"red"` or `"green"`. A server response enum is a good fit for associated values because a success case may need to store a username, token, or other returned data.

## 2. Side-by-Side Comparison

| Feature | Raw Values | Associated Values |
| --- | --- | --- |
| Purpose | Map each case to one fixed value | Store extra data for a specific enum instance |
| When assigned | In the enum definition | When creating the case value |
| Can vary per instance? | No | Yes |
| Common types | `String`, `Int`, `Double` | Almost any Swift type |
| Access pattern | `case.rawValue` | Pattern matching with `switch` or `if case` |
| Reverse lookup | Often supported with `Enum(rawValue:)` | Not automatic |
| Typical use | Status codes, API strings, stored identifiers | Responses, state machines, rich domain data |

## 3. Key Differences Explained

### Fixed value vs stored payload

A raw value is part of the enum case definition itself. Every time you use that case, its raw value is the same. An associated value is a payload attached to one конкрет enum instance, so it can change from one use to another.

Here is a raw value enum:

```swift
enum Direction: String {
    case north = "N"
    case south = "S"
    case east = "E"
    case west = "W"
}
```

Each direction always has the same string code.

Here is an associated value enum:

```swift
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}
```

Each barcode value can carry different data depending on the case and the specific instance.

### How you read them

Raw values are easy to read using the `rawValue` property.

```swift
let direction = Direction.north
print(direction.rawValue)
```

Output (tested with Swift 6.4):

```text
N
```

This prints the fixed raw value for the case.

Associated values are extracted with pattern matching.

```swift
let code = Barcode.qrCode("SWIFT-123")

switch code {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case .qrCode(let value):
    print("QR code: \(value)")
}
```

Output (tested with Swift 6.4):

```text
QR code: SWIFT-123
```

This works because associated values are not available through `rawValue`; they must be matched and unpacked.

### When to use each

Choose raw values when your enum cases represent stable codes, labels, or identifiers. Choose associated values when cases need to carry meaningful data that belongs to a specific case instance.

- Use **raw values** for things like file formats, API status names, weekdays, and persisted string codes.
- Use **associated values** for things like network results, media items, screen state, and parser tokens.

## 4. When to Use Each

### Use raw values when the case has one fixed representation

- Mapping app settings to stored strings
- Converting API text values into Swift types
- Working with numeric codes that should stay consistent
- Displaying a known label or identifier

Example:

```swift
enum FileType: String {
    case pdf = "application/pdf"
    case jpeg = "image/jpeg"
    case plainText = "text/plain"
}
```

Each file type has one exact MIME string, so raw values are a natural fit.

### Use associated values when the case needs runtime data

- Returning success with data or failure with an error message
- Representing user actions that carry IDs or text
- Modeling state such as loading, loaded data, or failed request
- Storing different data shapes under one enum type

Example:

```swift
enum LoginResult {
    case success(String)
    case failure(String)
}
```

Here, the success and failure cases each carry data that changes at runtime.

## 5. Code Examples

### Example 1: Raw values with strings

This example shows an enum whose cases map to fixed strings.

```swift
enum Season: String {
    case spring = "Spring"
    case summer = "Summer"
    case autumn = "Autumn"
    case winter = "Winter"
}

let currentSeason = Season.summer
print(currentSeason.rawValue)
```

Output (tested with Swift 6.4):

```text
Summer
```

The output is the raw string `Summer`.

### Example 2: Creating from a raw value

One benefit of raw values is that Swift can often build an enum from the raw value using an initializer.

```swift
enum HTTPStatus: Int {
    case ok = 200
    case notFound = 404
    case serverError = 500
}

let status = HTTPStatus(rawValue: 404)
print(status as Any)
```

Output (tested with Swift 6.4):

```text
Optional(main.HTTPStatus.notFound)
```

This returns an optional because the raw value might not match any case.

### Example 3: Associated values for API results

This enum stores different kinds of data depending on the result.

```swift
enum APIResponse {
    case success(String)
    case failure(Int, String)
}

let response = APIResponse.failure(401, "Unauthorized")

switch response {
case .success(let message):
    print("Success: \(message)")
case .failure(let code, let reason):
    print("Error \(code): \(reason)")
}
```

Output (tested with Swift 6.4):

```text
Error 401: Unauthorized
```

The failure case carries both a code and a message, which raw values cannot express.

### Example 4: Named associated values

Associated values can be clearer when you name the stored pieces of data.

```swift
enum Shape {
    case rectangle(width: Double, height: Double)
    case circle(radius: Double)
}

let shape = Shape.rectangle(width: 10.0, height: 5.0)

switch shape {
case .rectangle(let width, let height):
    print("Rectangle: \(width) x \(height)")
case .circle(let radius):
    print("Circle radius: \(radius)")
}
```

Output (tested with Swift 6.4):

```text
Rectangle: 10.0 x 5.0
```

This makes the meaning of each value easier to understand when creating enum instances.

## 6. Common Mistakes

### Mistake 1: Trying to read an associated value with `rawValue`

Beginners often assume every enum has a `rawValue` property. That is only true for enums declared with a raw value type.

**Problem:** This code treats an enum with associated values as if it had fixed raw values, so Swift reports that the member does not exist.

```swift
enum ResultState {
    case success(String)
    case failure(String)
}

let state = ResultState.success("Done")
print(state.rawValue)
```

**Fix:** Use pattern matching to extract associated values.

```swift
enum ResultState {
    case success(String)
    case failure(String)
}

let state = ResultState.success("Done")

switch state {
case .success(let message):
    print(message)
case .failure(let message):
    print(message)
}
```

Output (tested with Swift 6.4):

```text
Done
```

The corrected version works because associated values must be unpacked from the enum case.

### Mistake 2: Trying to assign different raw values at runtime

Raw values are fixed in the enum definition. You cannot pass a new raw value each time you create a case.

**Problem:** This code tries to use a raw-value enum case like a function call with changing input, but raw values are not runtime payloads.

```swift
enum UserRole: String {
    case admin
    case guest
}

let role = UserRole.admin("super-admin")
```

**Fix:** Use associated values if the case must carry changing data.

```swift
enum UserRole {
    case admin(String)
    case guest(String)
}

let role = UserRole.admin("super-admin")
```

The corrected version works because associated values allow the case to store data supplied at creation time.

### Mistake 3: Forgetting that `Enum(rawValue:)` returns an optional

When you create a raw-value enum from external input, the input might not match any case.

**Problem:** This code assumes every integer will map to a valid case, but invalid input produces `nil`, which can lead to the error `Value of optional type must be unwrapped`.

```swift
enum Priority: Int {
    case low = 1
    case medium = 2
    case high = 3
}

let priority = Priority(rawValue: 5)
print(priority.rawValue)
```

**Fix:** Safely unwrap the optional before using it.

```swift
enum Priority: Int {
    case low = 1
    case medium = 2
    case high = 3
}

let priority = Priority(rawValue: 2)

if let priority {
    print(priority.rawValue)
}
```

Output (tested with Swift 6.4):

```text
2
```

The corrected version works because it handles the possibility that the raw value does not match a case.

## 7. Tradeoffs and Edge Cases

- **Raw values are simpler** when you need a stable mapping, but they cannot store changing data.
- **Associated values are more expressive**, but they require pattern matching to read and compare their contents.
- If you need to create an enum from external text or numbers, raw values are often more convenient because `Enum(rawValue:)` is built in.
- If cases need different shapes of data, associated values are usually the better design.
- Two enum values with the same case but different associated values are different instances, such as `.success("A")` and `.success("B")`.
- Raw value enums must use one raw value type for all cases, such as all `String` or all `Int`.
- Associated value enums do not automatically support reverse lookup from one value the way raw value enums do.

> A common design clue is this: if you are asking, “What fixed code represents this case?” think raw values. If you are asking, “What data should travel with this case?” think associated values.

## 8. Decision Guide

- If every case has one permanent string, number, or code, use **raw values**.
- If the case needs to store data provided at runtime, use **associated values**.
- If you need to build the enum from saved text like `"pending"` or `200`, raw values are usually easier.
- If one case stores one value and another case stores several values, use associated values.
- If you need a compact external representation and rich internal modeling, you may use associated values in one enum and convert to another raw-value enum when needed.

## 9. Key Points

- Raw values are fixed values defined once for each enum case.
- Associated values are per-instance payloads supplied when creating a case.
- Use `rawValue` only with raw-value enums.
- Use `switch` or pattern matching to extract associated values.
- `Enum(rawValue:)` returns an optional because the lookup can fail.
- Raw values are best for stable identifiers; associated values are best for dynamic data.

## 10. Final Summary

Swift enum raw values and associated values may look related, but they serve very different purposes. Raw values map each case to one fixed underlying value, which makes them useful for stable identifiers, saved settings, and external codes. Associated values attach runtime data to individual enum instances, which makes them ideal for responses, state, and rich domain models.

When choosing between them, focus on the job your enum needs to do. If the case always means the same fixed string or number, choose raw values. If the case needs to carry data that changes from one instance to another, choose associated values. As a next step, practice writing enums that use `switch` pattern matching well, since that is the key skill for working confidently with associated values.
