> ## Content Index
> Fetch the complete content index at: https://developerinsider.co/llms.txt
> Use this file to discover other available public pages before exploring further.

# Advanced Enum (Enumerations) by Example - Swift Programming Language
- URL: https://developerinsider.co/advanced-enum-enumerations-by-example-swift-programming-language/
- Published: 2017-08-29T10:59:30.000Z
- Updated: 2018-03-29T17:01:03.000Z
- Author: Vineet Choudhary
- Tags: Swift, iOS, Swift4

## 1\. Properties

We can't add actual stored properties to an `enum`, but we can create computed properties. The value of computed properties can be based on the enum value or enum associated value.

Let's create an enum called `Device`. It's contain a computed property called `year`, which return the first appearance of that device.

```swift
enum Device {
	case iPad
	case iPhone
	
	var year: Int {
		switch self {
			case .iPhone: 
				return 2007
			case .iPad: 
				return 2010
		}
	}
}

let device = Device.iPhone
print(device.year)
//prints "2007"

```

## 2\. Methods

We can also define methods in an `enum`. Methods in enums exist for every enum case. So if we want to have specific code for specific cases, we need a `switch` to determine the correct code path for that specific case.

```swift
enum Device { 
	case iPad
	case iPhone
	
    func introduced() -> String {
		switch self {
			case .iPhone: 
				return "\(self) was introduced 2007"
			case .iPad: 
				return "\(self) was introduced 2010"
		}
	}
}

let device = Device.iPhone
print (device.introduced())
//prints "iPhone was introduced 2007"

```

## 3\. Nested Enums

We can nest enumerations one inside another, this allows you to structure hierarchical enums to be more organized and clear.

#### 3.1 Create a Nested Enumerations

Imagine a character in a Roll Playing Game. Each character can have a weapon, all characters have access to the same set of weapons. So, Let's create an enum called `Character`. It contains other enums called, `Weapon` and `Helmet`.

```swift
enum Character {
	enum Weapon {
		case bow
		case sword
		case dagger
	}
	
	enum Helmet {
		case wooden
		case iron
    	case diamond
	}

	case thief(weapon: Weapon, helmet: Helmet)
	case warrior(weapon: Weapon, helmet: Helmet)
	
	func getDescription() -> String {
		switch self {
			case let .thief(weapon, helmet):
				return "Thief chosen \(weapon) and \(helmet) helmet"
			case let .warrior(weapon, helmet):
				return "Warrior chosen \(weapon) and \(helmet) helmet"
		}
	}
}

```

#### 3.2 Initialization

Now, We have a hierarchical system to describe the various items that our character has access to.

```swift
let helmet = Character.Helmet.iron
print(helmet)
//prints "iron"

let weapon = Character.Weapon.dagger
print(weapon)
//prints "weapon"

let character1 = Character.warrior(weapon: .sword, helmet: .diamond)
print(character1.getDescription())
// prints "Warrior chosen sword and diamond helmet"
 
let character2 = Character.thief(weapon: .bow, helmet: .iron)
print(character2.getDescription())
//prints "Thief chosen bow and iron helmet"

```

## 4\. Containing Enums

We can also embed enums in `structs` or `classes`. This pattern is very important for app business logic. Also, helps in keeping related information together.

#### 4.1 Create a Struct which containing Enums

with our previous example:

```swift
struct Character {
	enum CharacterType {
		case thief
		case warrior
	}
	enum Weapon {
		case bow
		case sword
		case dagger
	}
	let type: CharacterType
	let weapon: Weapon
}

```

#### 4.2 Initialization

To initialize a `Character`, we have to choose `CharacterType` and `Weapon`.

```swift
let character = Character(type: .warrior, weapon: .sword)
print("\(character.type) chosen \(character.weapon)")
//warrior chosen sword

```

## 5\. Mutating Method

We may create a mutating function that can set the implicit `self` parameter to be a different case from the same enumeration.

The example below defines an enumeration for a three-state switch. The switch cycles between three different power states (`off`, `low` and `high`) every time its `next()` method is called.

```swift
enum TriStateSwitch {
	case off
	case low
	case high
	mutating func next() {
		switch self {
			case .off:
				self = .low
			case .low:
				self = .high
			case .high:
			self = .off
		}
	}
}

var ovenLight = TriStateSwitch.off
ovenLight.next() // ovenLight is now equal to .low
ovenLight.next() // ovenLight is now equal to .high
ovenLight.next() // ovenLight is now equal to .off again

```

## 6\. Static Method

We can also create `static` methods in `enum`. Let's create an enum called, `Device`. It contains a static function which returns `Device` based on the name of the parameter used in the function.

```swift
enum Device {
	case iPhone
	case iPad

	static func getDevice(name: String) -> Device? {
		switch name {
			case "iPhone":
				return .iPhone
			case "iPad":
				return .iPad
			default:
				return nil
		}
	}
}

if let device = Device.getDevice(name: "iPhone") {
	print(device) 
	//prints iPhone
}

```

## 7\. Custom Init

We may add a custom `init` method to create an object of our choice.

```swift
enum IntCategory {
	case small
	case medium
	case big
	case weird

	init(number: Int) {
		switch number {
			case 0..<1000 :
				self = .small
			case 1000..<100000:
				self = .medium
			case 100000..<1000000:
				self = .big
			default:
				self = .weird
		}
	}
}

let intCategory = IntCategory(number: 34645)
print(intCategory)
//prints medium

```

## 8\. Protocol Oriented Enum

Swift protocols define an interface or type that other structures can conform to. In this case our enum will conform to it.

In order to understand protocol with enums, We'll create a Game. In which, a player could be either `.dead` or `.alive`. When alive, the player has a number of hearts/lives. If the number goes to zero, the player becomes dead.

#### 8.1 Create Protocol

Let's create a `protocol` called, `LifeSpan`. It contains one property, `numberOfHearts` and two mutating functions which will be used to increase/decrease a player's heart.

```swift
protocol LifeSpan {
	var numberOfHearts: Int { get }
	mutating func getAttacked() // heart -1
	mutating func increaseHeart() // heart +1
}

```

#### 8.2 Create Enum

Now, create an `enum` called `Player`. It conforms to protocol `LifeSpan`. There are two cases. The object can be either dead or alive. The alive case contains an associated value called `currentHeart`. It also contains a gettable computed property, `numberOfHearts`. `numberOfHearts` is determined based on whether self is case or alive.

```swift
enum Player: LifeSpan {
	case dead
	case alive(currentHeart: Int)
	
	var numberOfHearts: Int {
		switch self {
			case .dead: return 0
			case let .alive(numberOfHearts): return numberOfHearts
		}
	}
	
	mutating func increaseHeart() {
		switch self {
			case .dead:
				self = .alive(currentHeart: 1)
			case let .alive(numberOfHearts):
				self = .alive(currentHeart: numberOfHearts + 1)
		}
	}
	
	mutating func getAttacked() {
		switch self {
			case .alive(let numberOfHearts):
				if numberOfHearts == 1 {
					self = .dead
				} else {
					self = .alive(currentHeart: numberOfHearts - 1)
				}
			case .dead:
			break
		}
	}
}

```

#### 8.3 Play Game

Let's play the Game.

```swift
var player = Player.dead // .dead

player.increaseHeart()  // .alive(currentHeart: 1)
print(player.numberOfHearts) //prints 1

player.increaseHeart()  // .alive(currentHeart: 2)
print(player.numberOfHearts) //prints 2

player.getAttacked()  // .alive(currentHeart: 1)
print(player.numberOfHearts) //prints 1

player.getAttacked() // .dead
print(player.numberOfHearts) // prints 0

```

## 9\. Extensions

We can also extend the enums. The most apparent use case for this is keeping enum cases and methods separate, so that a reader of your code can easily digest the enum and after that move on to the methods:

```swift
enum Entities {
    case soldier(x: Int, y: Int)
    case tank(x: Int, y: Int)
    case player(x: Int, y: Int)
}

```

Now, we can extend this enum with methods:

```swift
extension Entities {
    mutating func attack() {}
    mutating func move(distance: Float) {}
}

```

We can also write extensions to add support for a specific protocol:

```swift
extension Entities: CustomStringConvertible {
    var description: String {
        switch self {
            case let .soldier(x, y): return "Soldier position is (\(x), \(y))"
            case let .tank(x, y): return "Tank position is (\(x), \(y))"
            case let .player(x, y): return "Player position is (\(x), \(y))"
        }
    }
}

```

## 10\. Generic Enums

Enums can also be defined over generic parameters. Like structs, classes, and functions, the syntax looks identical.

```swift
enum Information<T1, T2> {
	case name(T1)
	case website(T1)
	case age(T2)
}

```

Let us initialize.

```swift
let info = Information.name("Bob") // Error

```

The compiler is able to recognize `T1` as String based on "Bob". However, the type of `T2` is not defined yet. Therefore, you must define both `T1 `and `T2` explicitly as shown below.

```swift
let info =Information<String, Int>.age(20) 
print(info) //prints age(20)

```

## 11\. Recursive Enums

Let's create an enum called, `ArithmeticExpression`. It contains three cases with associated types. Two of the cases contain its own enum type, `ArithmeticExpression`. The `indirect` keyword tells the compiler to handle this enum case indirectly.

> Enums and cases can be marked indirect, which causes the associated value for the enum to be stored indirectly, allowing for recursive data structures to be defined.

```swift
indirect enum ArithmeticExpressions {
	case number(Int)
	case addition(ArithmeticExpressions, ArithmeticExpressions)
	case multiplication(ArithmeticExpressions, ArithmeticExpressions)
}

func evaluate(_ expression: ArithmeticExpressions) -> 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)
	}
}

let expression = evaluate(ArithmeticExpressions.addition(.number(1), .number(2)))
print(expression) //prints 3

```

---

#### You can download the swift playground of all above examples from [Here](https://github.com/developerinsider/developer-insider-content/blob/master/POST/iOS/Swift/Playgrounds/AdvancedEnum.playground.zip?raw=true&ref=developerinsider.co)

---