Enums in Swift with Real Life Examples
Introduction
Enumeration (Enum) 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.
func dayType(for day: String) -> String {
switch day {
case: "Saturday", "Sunday": return "Weekend"
case: "Monday", "Tuesday", "Wednessday", "Thursday", "Friday": return "Weekday"
default: return "This is not a valid date"
}
}
let result1 = dayType(for: "Sunday") //will return "Weekend"
let result2 = dayType(for: "Thursday") //will return "Weekday"
let result3 = dayType(for: "fridayys") //will return "This is not a valid date"
Assuming we have a method named dayType
that accept any day of the week then return Weekend
for Saturday and Sunday
, Weekday
for Monday, Tuesday, Wednessday, Thursday and Friday
and return This is not a valid date
when it fails to recognised what was been passed into it. The function will work as aspected but what happens when you actually want to pass let say a friday
but you mistakingly type fridaysy
even though what we actually wanted to type was friday
. The switch above goes to the default This is not a valid date
. That is the type-safty enum
brings into the table. It help us to avoid such risk by providing common type for group of related values like below:
enum Day {
case Sunday
case Monday
case Tuesday
case Wednessday
case Thursday
case Friday
case Saturday
}
/** Rewriting the date type function */
func dayType(for day: Day) {
switch day {
case Day.Saturday, Day.Sunday:
return "Weekend"
case Day.Monday, Day.Tuesday, Day.Wednessday, Day.Thursday, Day.Friday
return "Weekday"
}
}
let result1 = dayType(for: Day.Sunday) //will return "Weekend"
We have been able to eliminate the use of String by defining an enum to hold the days. We don’t need to use the append the Day
before every declaration of the day enum within the switch statement because we already assigned day to be a type of Day. Hence the dayType function can be reduce to below:
/** Rewriting the date type function */
func dayType(for day: Day) {
switch day {
case .Saturday, .Sunday:
return "Weekend"
case .Monday, .Tuesday, .Wednessday, .Thursday, .Friday
return "Weekday"
}
}
We have to understand enum is best suited for declaring types with finite sets of possible states, like Direction (north, south, west, east), Movement (Up, down, left, right) etc.
Enum Values
We can assign value to each enum
case. This is useful if the enum
itself indeed relates to something
// You can also map to strings
enum Week: String {
case Sunday = "Weekday"
case Monday = "Weekday"
case Tuesday = "Weekday"
case Wednessday = "Weekday"
case Thursday = "Weekday"
case Friday = "Weekend"
case Saturday = "Weekend"
}
// You can also map to Int
enum Movement: Int {
case Left = 0
case Right = 1
case Top = 2
case Bottom = 3
}
// Or to floating point
enum Constants: Double {
case π = 3.14159
case e = 2.71828
case φ = 1.61803398874
case λ = 1.30357
}
We can access the value assigned to an enum with the rawValue
keyword. To access the Week enum above, we can use Week.Monday.rawValue
which will return Weekday
.
Enum Associate Values
Associate values are a fantastic way of attaching additional information to an enum
case. Say you’re writing a trade engine, there are two different possible trade types, Buy and Sell that will have a specific stock and amount. We can represent this using associate enum values like below
/** associate without labels */
enum Trade {
case Buy(String, amount)
case Sell(String, Int)
}
Trade.Buy("Firstbank PLC", 300)
Trade.Sell("Firstbank PLC", 700)
/** associate with labels */
enum Trade {
case Buy(stock: String, amount: Int)
case Sell(stock: String, amount: Int)
}
Trade.Buy(stock: "Firstbank PLC", amount: 300)
Trade.Sell(stock: "Firstbank PLC", amount: 700)
Enum Methods
We can also define methods on an enum
like below
enum AppleDevice {
case iPad
case iPhone
case AppleTv
case AppleWatch
func description() -> String {
return "This is an apple device"
}
}
AppleDevice.iPad.description() //will return "This is an apple device"
AppleDevice.iPhone.description() //will return "This is an apple device"
Notice the code snippet above, the func description will return “This is an apple device” for every case in the enum
. To avoid this, we can make use of switch statement within the description method like below
enum AppleDevice {
case iPad, iPhone, AppleTv, AppleWatch
func description() -> String {
switch self {
case .iPad: return "\(self) was introduced 2006"
case .iPhone: return "\(self) was introduced 2007"
case .AppleTv: return "\(self) was introduced 2010"
case .AppleWatch: return "\(self) was introduced 2014"
}
}
}
AppleDevice.iPad.description() //will return "iPad was introduced 2006"
AppleDevice.iPhone.description() //will return "iPhone was introduced 2007"