Syntax

enum Direction {
		case up
		case down
		case left
		case right
}

Multiple case can appear on a single line, separated by commas:

enum {
		case up, down, left, right
}

Use the Enumeration

var dir = Direction.up

When we want to modify the var after the initialized, we can use a shorter form of the enumeration.

var dir = Direction.up
dir = .down    // The value's type has been inferred when the value is in initializing.

Matching Enumeration Values with a Switch Statement

enum Direction {
    case up
    case down
    case left
    case right
}
var dir = Direction.right
switch dir {
case .up:
    print("Go up")
case .down:
    print("Go down")
case .left:
    print("Go left")
case .right:
    print("Go right")
}

Iterating over Enumeration Cases

Conform to the CaseIterable protocol, to make the enumeration’s case be iterable.

enum Beverage: CaseIterable {
    case coffee, tea, juice
}
let cases = Beverage.allCases
for c in cases {
    print(c)
}
  • Result:

    coffee tea juice

Associated Values

Here has two reference with associated values of type (Int, Int, Int, Int) or (String), use enumeration can choose one of them.

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

Use the enumeration to create value, choose a type of barcode

But They can store only one of them at any given time.

var product = Barcode.upc(8, 810, 222, 888)
product = .qrCode("KINGKIYK")              // Assign another type to the same product.

Use switch to check the type, and use let or var to extract each associated value.

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

If all the associated values are extracted as constants or if all are extracted as variable, we can use var or let annotation before the case name, for brevity.

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

Raw Values

As an alternative to associated values, enumeration cases come pre-populated with default values(raw values), which are all of the same type.

Each raw value must be unique within its enumeration declaration.

enum somechar: Character {
		case tab = "\t"
		case lineFeed = "\n"
		case carriageReturn = "\r"
}

In Enumeration:

  • Raw values are set by default, choose one to use when we need.
  • Associated values are set before we want to use it.

Implicitly Assigned Raw Values

When we define an enumeration that store integer or string raw values, it’s no need to explicitly assign for each case, Swift can infer from the first one case.

  • Implicitly assign with integer
enum Day: Int{
    case Sunday = 1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
}
print(Day.Monday.rawValue)
// Print: 「2」
  • Implicitly assign with string

    enum Direction: String{
        case up, down, left, right
    }
    
    print(Direction.left.rawValue)
    // Print: 「left」
    

Initializing from a Raw Value

enum Day: Int{
    case Sunday = 1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
}

enum Direction: String{
    case up, down, left, right
}

let day = Day(rawValue: 3)     // 'day' is of type 'Day?' and equals to Day.Tuesday 
let dir = Direction(rawValue: "right")
let other = Day(rawValue: 8)   // Not found rawValue, 'other' will be 'nil'

print(day!)
print(dir)
print(other)
  • Result:

    Tuesday Optional(Page_Contents.Direction.right) nil

Recursive Enumerations

Base on the associated values, recursively use the the associated operation.

Use the indirect keyword to indicate that the associated value will be called recursively.

The <T> indicate to use generic type.

enum Arithmetic<T> {
    case num(T)
    indirect case add(Arithmetic, Arithmetic)
    indirect case multiply(Arithmetic, Arithmetic)
}

Another way to indicate the indirect :

indirect enum Arithmetic<T> {
    case num(T)
    case add(Arithmetic, Arithmetic)
    case multiply(Arithmetic, Arithmetic)
}

Use the recursive, and access the value with recursive function.

let five = Arithmetic<Int>.num(5)
let nine = Arithmetic<Int>.num(9)

let sum = Arithmetic.add(five, nine)
let multiply = Arithmetic.multiply(sum, five)

func evaluate(_ expression: Arithmetic<Int>) -> Int {
    switch expression {
    case let .num(value):        // Here use the value binding to match the expression.
        return value
    case let .add(first, second):
        return evaluate(first) + evaluate(second)
    case let .multiply(first, second):
        return evaluate(first) * evaluate(second)
    }
}
print(evaluate(sum))        // 5 + 9 == 14
print(evaluate(multiply))   // (5 + 9) * 5 == 70
  • Result:

    14 70