Enumeration in Swift


Introduction to Enumerations in Swift

In Swift, an enumeration (enum) is a powerful data type that allows you to define a group of related values in a type-safe way. Enums are particularly useful when dealing with fixed categories, options, or states in an application.

Swift’s enums are more advanced than those in other languages because they can:

  • Store associated values for each case.
  • Have raw values of different types.
  • Support computed properties and methods.
  • Conform to protocols, making them more flexible.

Why Use Enumerations in Swift?


  • Improves Code Readability – Organizes related values neatly.
  • Prevents Invalid Values – Restricts input to predefined cases.
  • Enhances Type Safety – Reduces errors with strict type checking.
  • Works with Switch Statements – Provides cleaner decision-making logic.

Basic Syntax of an Enum

enum EnumName {
     case case1
     case case2
     case case3
}

Example 1: Defining and Using an Enum

enum Direction {
     case north
     case south
     case east
     case west
}

var moveDirection: Direction = .north
print(moveDirection) // north

You can also assign an enum value using shorthand:

moveDirection = .south

Output

north

1. Using Enums in a Switch Statement

Enums are often used with switch statements for better control flow.

enum TrafficLight {
     case red, yellow, green
}

let signal = TrafficLight.red

switch signal {
     case .red:
         print("Stop")
     case .yellow:
         print("Get Ready")
     case .green:
         print("Go")
}

Output

Stop

2. Raw Values in Enumerations

Enums can have raw values, which are default values assigned to each case. These raw values can be String, Int, Double, or Character.

enum Day: Int {
     case monday = 1
     case tuesday, wednesday, thursday, friday
}

print(Day.tuesday.rawValue) // 2

Output

2

Here, monday is explicitly assigned 1, and the subsequent cases automatically get incremented values.

3. Initializing an Enum from a Raw Value

Enums with raw values can be initialized using init?(rawValue:).

if let today = Day(rawValue: 3) {
     print("Today is \(today)")
} else {
     print("Invalid day")
}

Output

Today is wednesday

4. Associated Values in Enums

Enums in Swift can store different types of values associated with each case.

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

var productCode = Barcode.upc(8, 85909, 51226, 3)
print(productCode) // upc(8, 85909, 51226, 3)

To extract associated values, use a switch statement:

switch productCode {
     case .upc(let part1, let part2, let part3, let part4):
         print("UPC Code: \(part1)-\(part2)-\(part3)-\(part4)")
     case .qrCode(let code):
         print("QR Code: \(code)")
}

Output

UPC Code: 8-85909-51226-3

5. Enum with Methods

You can define methods inside an enum to add functionality.

enum Temperature {
     case hot, cold

     func description() -> String {
         switch self {
             case .hot: return "It's hot outside!"
             case .cold: return "It's cold outside!"
         }
     }
}

let currentTemp = Temperature.hot
print(currentTemp.description()) // It's hot outside!

Output

It's hot outside!

6. Mutating Enums (Changing Enum Value in Methods)

By default, enums are immutable. To modify an enum’s value inside a method, you need to mark it as mutating.

enum LightSwitch {
     case on, off

     mutating func toggle() {
         self = (self == .on) ? .off : .on
     }
}

var switchState = LightSwitch.off
switchState.toggle()
print(switchState) // on

Output

on

7. Enum with CaseIterable Protocol (Looping Through Cases)

If you want to iterate over all cases of an enum, conform it to CaseIterable.

enum Beverage: CaseIterable {
     case coffee, tea, juice, water
}

for drink in Beverage.allCases {
     print(drink)
}

Output

coffee
tea
juice
water

8. Enum with Custom Initializer

You can define a custom initializer in an enum.

enum Size {
     case small, medium, large

     init?(value: Int) {
         switch value {
             case 1: self = .small
             case 2: self = .medium
             case 3: self = .large
             default: return nil
         }
     }
}

if let size = Size(value: 2) {
     print("Selected size: \(size)")
} else {
     print("Invalid size")
}

Output

Selected size: medium

9. Enum with Protocol Conformance

Enums can conform to protocols for added functionality.

protocol Describable {
     func describe() -> String
}

enum Vehicle: Describable {
     case car, bike

     func describe() -> String {
         switch self {
             case .car: return "A four-wheeled vehicle"
             case .bike: return "A two-wheeled vehicle"
         }
     }
}

let myVehicle = Vehicle.bike
print(myVehicle.describe()) // A two-wheeled vehicle

Output

A two-wheeled vehicle

Best Practices for Using Enums in Swift


  • Use enums for fixed categories or states to ensure type safety.
  • Use raw values when each case corresponds to a predefined value.
  • Use associated values when each case needs extra information.
  • Leverage switch statements for cleaner control flow.
  • Conform to CaseIterable when needing iteration over all cases.
  • Use computed properties and methods to extend functionality.
  • Ensure proper memory management when using enums in large applications.

Conclusion

Swift enumerations (enums) are a powerful and flexible way to work with related values efficiently. Unlike enums in other languages, Swift allows raw values, associated values, computed properties, and protocol conformance, making them highly functional.

Using enums correctly improves code organization, type safety, and readability, making Swift programming more efficient and maintainable.