0
0
Swiftprogramming~15 mins

Raw values for enums in Swift - Deep Dive

Choose your learning style9 modes available
Overview - Raw values for enums
What is it?
Raw values for enums in Swift are fixed values assigned to each case of an enumeration. These values can be strings, numbers, or other literal types. They allow you to associate a simple, constant value with each enum case for easy identification or storage. This helps enums work smoothly with external data or when you need a specific value for each case.
Why it matters
Raw values exist to connect enum cases with meaningful, fixed data like IDs or names. Without raw values, enums would only represent named options without any direct value, making it harder to save, compare, or communicate enum data outside the program. Raw values make enums practical for real-world tasks like reading from files, databases, or user input.
Where it fits
Before learning raw values, you should understand basic enums and how to define them in Swift. After mastering raw values, you can explore associated values for enums, which allow storing different data per case, and learn about using enums with protocols and pattern matching.
Mental Model
Core Idea
Raw values give each enum case a fixed, simple value that identifies it uniquely and consistently.
Think of it like...
Think of enum cases as different types of keys on a keychain, and raw values as the unique labels or numbers stamped on each key to tell them apart easily.
Enum Example with Raw Values
┌───────────────┐
│ enum Color    │
│ ┌───────────┐ │
│ │ case red = "R" │
│ │ case green = "G" │
│ │ case blue = "B" │
│ └───────────┘ │
└───────────────┘
Each case has a raw value: "R", "G", "B"
Build-Up - 7 Steps
1
FoundationUnderstanding Basic Enums
🤔
Concept: Learn what enums are and how to define simple cases without values.
In Swift, enums group related values under one type. For example: enum Direction { case north case south case east case west } This defines four named options but no values attached.
Result
You can create variables of type Direction and assign one of the four cases.
Knowing basic enums sets the stage for adding raw values, which extend enums with fixed data.
2
FoundationIntroducing Raw Values
🤔
Concept: Raw values assign a fixed, literal value to each enum case.
You can add raw values by specifying a type and assigning values: enum Planet: Int { case mercury = 1 case venus = 2 case earth = 3 } Here, each planet has a number as its raw value.
Result
Each case now has a number you can access, like Planet.earth.rawValue which is 3.
Raw values link enum cases to simple data, making them more useful for storage and comparison.
3
IntermediateAccessing Raw Values
🤔
Concept: Learn how to get the raw value from an enum case.
You use the .rawValue property: let p = Planet.venus print(p.rawValue) // prints 2 This lets you read the fixed value tied to the case.
Result
Output is the raw value, e.g., 2 for venus.
Accessing raw values lets you use enums in places where simple values are needed, like saving to a file.
4
IntermediateCreating Enums from Raw Values
🤔Before reading on: do you think you can create an enum case from any raw value, or only from valid ones? Commit to your answer.
Concept: You can try to create an enum case from a raw value, but it might fail if the value doesn't match any case.
Use the initializer init?(rawValue:) which returns an optional: if let planet = Planet(rawValue: 3) { print("Planet found: \(planet)") } else { print("No planet with that raw value") } If the raw value matches a case, you get that case; otherwise, nil.
Result
Output: Planet found: earth If you try Planet(rawValue: 10), it returns nil.
Understanding this prevents crashes and helps safely convert raw data into enum cases.
5
IntermediateRaw Value Types Allowed
🤔
Concept: Raw values must be literals of certain types like Int, String, or Float.
Swift supports raw values of types: Int, String, Character, and floating-point types. Example: enum CompassPoint: String { case north = "N" case south = "S" } You cannot use complex types like arrays or dictionaries as raw values.
Result
You can assign and access raw values only if they are simple literal types.
Knowing allowed types helps avoid errors and choose the right raw value type for your use case.
6
AdvancedImplicit Raw Value Assignment
🤔Before reading on: do you think Swift requires you to assign every raw value explicitly, or can it fill some in automatically? Commit to your answer.
Concept: Swift can automatically assign raw values for some types like Int and String if you omit them.
For Int raw values, Swift starts at 0 and counts up: enum Weekday: Int { case monday, tuesday, wednesday } Here monday = 0, tuesday = 1, wednesday = 2. For String raw values, if omitted, the case name is used: enum Fruit: String { case apple, banana } apple.rawValue is "apple".
Result
Raw values are assigned automatically, saving typing and reducing errors.
Understanding implicit assignment helps write cleaner code and avoid bugs from manual numbering.
7
ExpertRaw Values vs Associated Values
🤔Before reading on: do you think raw values and associated values serve the same purpose in enums? Commit to your answer.
Concept: Raw values are fixed constants for each case, while associated values store extra data per instance and can vary.
Raw values are declared once per case and are the same for all instances. Associated values let you attach different data when creating each enum instance: enum Barcode { case upc(Int, Int, Int, Int) case qrCode(String) } Raw values can't do this variability. Trying to mix both in one enum is not allowed.
Result
You learn when to use raw values for fixed identifiers and when to use associated values for flexible data.
Knowing this distinction prevents confusion and helps design enums that fit your data needs.
Under the Hood
Swift enums with raw values are backed by a fixed type like Int or String. Each case is assigned a constant value stored in the enum's memory representation. The compiler generates code to map between cases and raw values, including an initializer that tries to find a case matching a raw value. This mapping is done efficiently using lookup tables or switch statements internally.
Why designed this way?
Raw values were designed to let enums interoperate with external data and APIs that use simple values. This design balances type safety with practical needs like serialization. Alternatives like associated values offer flexibility but don't provide a fixed identifier, so raw values fill that gap cleanly.
Enum Raw Value Mechanism
┌───────────────┐
│ Enum Case     │
│ ┌───────────┐ │
│ │ case A    │─┐
│ │ case B    │─┼─> Raw Value (Int/String)
│ │ case C    │─┘
│ └───────────┘ │
└───────────────┘
       │
       ▼
┌─────────────────────┐
│ Raw Value Lookup     │
│ init?(rawValue:)     │
│ Maps raw value to    │
│ enum case or nil     │
└─────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Can you assign different raw value types to different cases in the same enum? Commit to yes or no.
Common Belief:You can assign different raw value types to different cases in the same enum.
Tap to reveal reality
Reality:All cases in a Swift enum with raw values must share the same raw value type.
Why it matters:Trying to mix types causes compiler errors and confusion about the enum's type.
Quick: Does every enum case in Swift have a raw value by default? Commit to yes or no.
Common Belief:Every enum case automatically has a raw value even if you don't declare one.
Tap to reveal reality
Reality:Only enums explicitly declared with a raw value type have raw values; plain enums do not.
Why it matters:Assuming all enums have raw values can lead to errors when accessing .rawValue on enums without them.
Quick: Can you use raw values to store different data for each instance of the same enum case? Commit to yes or no.
Common Belief:Raw values let you store different data for each instance of an enum case.
Tap to reveal reality
Reality:Raw values are fixed constants per case and cannot vary between instances; use associated values for variable data.
Why it matters:Misusing raw values for variable data leads to design mistakes and runtime bugs.
Quick: Does the raw value initializer always return a valid enum case? Commit to yes or no.
Common Belief:The init?(rawValue:) initializer always returns a valid enum case.
Tap to reveal reality
Reality:It returns nil if the raw value does not match any case.
Why it matters:Ignoring this can cause unexpected nil values and crashes if not handled safely.
Expert Zone
1
Raw values can be automatically assigned for Int and String types, but this behavior differs subtly and can cause bugs if misunderstood.
2
Enums with raw values conform to the RawRepresentable protocol, enabling generic programming and interoperability with Swift's standard library.
3
Using raw values with enums allows seamless bridging to Objective-C APIs that expect primitive types, improving cross-language compatibility.
When NOT to use
Avoid raw values when you need to store different data per enum instance; use associated values instead. Also, if your enum cases don't need fixed identifiers or you want more complex behavior, consider using classes or structs.
Production Patterns
In production, raw values are often used for mapping enums to database IDs, JSON keys, or user interface strings. They enable easy serialization and deserialization. Developers also use raw values to implement switch statements that handle external data cleanly and to conform enums to protocols requiring raw representable types.
Connections
RawRepresentable Protocol
Raw values are implemented via the RawRepresentable protocol in Swift.
Understanding raw values helps grasp how Swift uses protocols to provide flexible, reusable enum functionality.
Serialization and Deserialization
Raw values enable enums to be converted to and from simple data formats like JSON or databases.
Knowing raw values clarifies how data moves between your program and external systems safely and efficiently.
Database Primary Keys
Raw values often represent fixed IDs similar to primary keys in databases.
Seeing raw values as keys helps understand their role in uniquely identifying enum cases in persistent storage.
Common Pitfalls
#1Assigning different raw value types to enum cases.
Wrong approach:enum Example { case one = 1 case two = "two" }
Correct approach:enum Example: Int { case one = 1 case two = 2 }
Root cause:Misunderstanding that all raw values must share the same type declared on the enum.
#2Assuming init?(rawValue:) never returns nil.
Wrong approach:let color = Color(rawValue: 10)! print(color)
Correct approach:if let color = Color(rawValue: 10) { print(color) } else { print("Invalid raw value") }
Root cause:Not handling the optional result of the failable initializer.
#3Using raw values to store variable data per enum instance.
Wrong approach:enum Status: String { case success = "OK" case error = "Error" } let s1 = Status.success let s2 = Status.success // Trying to assign different messages to s1 and s2 rawValue
Correct approach:enum Status { case success(message: String) case error(message: String) } let s1 = Status.success(message: "All good") let s2 = Status.success(message: "Partial success")
Root cause:Confusing raw values (fixed per case) with associated values (variable per instance).
Key Takeaways
Raw values assign fixed, literal data to each enum case, making enums more practical for real-world use.
All cases in a raw value enum share the same raw value type, such as Int or String.
You can access raw values with .rawValue and create enum cases from raw values safely using init?(rawValue:).
Raw values differ from associated values: raw values are constant per case, while associated values vary per instance.
Understanding raw values helps with data storage, serialization, and bridging between Swift and external systems.