Swift - Enumerations
Published: 2022-04-03 13:55:04

- An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code. enumeration definition defines a new type.
example : 

``` swift
enum CompassPoint {
    case north
    case south
    case east
    case west
}
```

- To have a collection of all of that enumeration’s cases, by conforming to CaseIterable protocol. The compiler can automatically provide an implementation of the CaseIterable requirements for any enumeration without associated values or @available attributes on its cases.

example :

``` swift
enum CompassDirection: CaseIterable {
    case north, south, east, west
}
for direction in CompassDirection.allCases {
    //body
}
```

### Associated Values
These are values(additional information) of any type that are stored alongside with case value. associated values can be of any type, and the value types can be different for each case. Each instance of enum can have different associated value for same type.

example :

``` swift
enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
```

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

###Raw Values

Enumeration cases can come pre-populated with default values called raw values, which are all of the same type. Each raw value must be unique within its enumeration declaration.The raw value for a particular enumeration case is always the same.

example :

``` swift
enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}
```

- For enumerations that store integer or string raw values, you don’t have to explicitly assign a raw value for each case.

example :

``` swift
enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
```

- access the raw value of an enumeration case with its **rawValue** property:

example :

``` swift
let earthsOrder = Planet.earth.rawValue // earthsOrder is 3
```

- If you define an enumeration with a raw-value type, the enumeration automatically receives an initializer that takes a value of the raw value’s type (as a parameter called rawValue) and returns either an enumeration case or nil. You can use this initializer to try to create a new instance of the enumeration.

example :

``` swift
let possiblePlanet = Planet(rawValue: 7) //optional(Planet.uranus)
```

**The raw value initializer is a failable initializer.**

## Recursive Enumeration 

A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration cases. You indicate that an enumeration case is recursive by writing indirect before it.

example :

``` swift
enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
// (5 + 4) * 2:
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
```

``` swift
func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}
print(evaluate(product)) // Prints "18"
```