1. Properties
Enum cannot create stored properties in enum, but can contain computed properties.
Now create an enum named Device, it contains a computed property named year, which returns the year of birth of that device.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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.
The following example uses the main switch of cases in the device enum to print out the production year of that divce:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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 create an enum inside an enum, which allows for more structured and clear code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
enum Animal { case fourLegs case twoLegs enum Dog { case chihuahua case fox } enum Bird { case penguin case ostrich } } |
4. Containing Enums
We can embed enum into struct or class.
4.1 Create a struct containing enum
For example, when making a game, we need to create a character, have weapons and “class”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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 init a new character, we must select the “class” and the weapon type:
1 2 3 4 |
let character = Character(type: .warrior, weapon: .sword) print("(character.type) chosen (character.weapon)") //warrior chosen sword |
5. Mutating Method
Create a mutating function that can change the case into another case to use in special cases. The following example defines an enum for three speeds of a fan:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
enum FanSpeedSwitch { case off case low case high mutating func next() { switch self { case .off: self = .low case .low: self = .high case .high: self = .off } } } var fanSpeed = FanSpeedSwitch.off fanSpeed.next() // fanSpeed is now equal to .low fanSpeed.next() // fanSpeed is now equal to .high fanSpeed.next() // fanSpeed is now equal to .off again |
6. Static Method
We can also create static methods in enum. The following example creates an enum named Device, which contains a static funtion that returns the enum Device based on the device name entered from the parameter of the static function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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
Create a custom initialization method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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
We can also conform to a protocol with enum.
To understand how to conform to the enum protocol. We will create a game in which a player can have 2 .dead or .alive states. When .alive, the player has health, and life stats. If these stats reach zero, the player will die (.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. Create a protocol called LifeSpan, which contains 1 property – numberOfHearts and 2 mutating functions that will be used to increase or decrease the player’s health index:
1 2 3 4 5 6 |
protocol LifeSpan { var numberOfHearts: Int { get } mutating func getAttacked() // heart -1 mutating func increaseHeart() // heart +1 } |
8.2 Create Enum
Now, create an Player enum, conform to the LifeSpan protocol, have 2 cases, .alive or .dead, .alive case assigned with the current blood index – currentHeart. A computed property calculates the character’s health index – numberOfHearts, based on the player’s .dead or .alive status.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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 create an enum extension to add properties and methods:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
enum Animal { case fourLegs case twoLegs enum Dog { case chihuahua case fox } enum Bird { case penguin case ostrich } } extension Animal { var description: String { switch self { case .fourLegs: return "Động vật 4 chân" case .twoLegs: return "Động vật 2 chân" } } mutating func swapAnimal() { switch self { case .fourLegs: self = .twoLegs case .twoLegs: self = .fourLegs } } } var animal = Animal.fourLegs print(animal.description) //"Động vật 4 chân" animal.swapAnimal() print(animal.description) //"Động vật 2 chân" |
10. Generic Enums
We can also create generic enum:
1 2 3 4 5 6 |
enum Information<T1, T2> { case name(T1) case website(T1) case age(T2) } |
Init:
let info = Information.name("Bob") // Error
The compiler reports an error because we just said T1 is a String based on the string “Bob”. However, the data type of T2 has not been defined. Therefore, we must define both T1 and T2 types:
1 2 3 |
let info =Information<String, Int>.age(20) print(info) //prints age(20) |