Enumeration

What is a Enumeration and when you should use it?

Tested on: Xcode 12.2, Swift 5.3

Enumeration is a group of related values and it allow you to work with these value in a safer way. To better understand, let's take the following example and we wants to find the meteorological season of the month depending on the input and we can use the following code:


Swift Code :

func findSessions(_ month: String) -> String{
   switch month {
   case "March", "April", "May":
      return "Spring"
   case "June", "July", "August":
      return "Summer"
   case "September", "October", "November"
      return "Autumn"
   case "December", "January", "February":
      return "Winter"
   default:
      return "invalid"
}

Now, you want to find the sessions of October and you call the function as shown below. However, There is a likely that you might mistype it for example, you type "Octr" instead of "October". Furthermore, you might short form of it and type "Oct" instead. Wouldn't it be good if you have a better way to do it? You can use enumeration to solve this problem.


Swift Code :

findSessins("October")
findSessins("Octr")
findSessins("Oct")

Output :

Autumn
invalid
invalid

Implemention of enumeration

1. Create Enum

Now, we should create an enumeration to solve the problem above. To create an enumeration you use the keyword enum and then you list out all the possible values ascases clauses as shown below:

Swift Code :

enum Month {
   case january
   case february
   case march
   case april
   case may
   case june
   case july
   case august
   case september
   case october
   case november
   case december
}

The code above creats an enumeration called Month with 12 values. In convention, the name of enumeration's first letter is an upper case just like as class or struct and the value start with a lower case just like a property.

To make life simple for developer like you and I. You can simplify the code into one line by using comma to separate each value.

Swift Code :

enum Month {
   case january, february, march, april, may, june, july, august, september, october, november, december
}

2. Using the enumeration in the Function

Using the function, findSessions we created just now. You can rewrite by using enumeration. So, it uses enumeration values to match instead of the string. Remember to change the data type of string to Month.

Swift Code :

func findSessions(_ month: Month) -> String{
   switch month {
   case Month.March, Month.April, Month.May:
      return "Spring"
   case Month.June, Month.July, Month.August:
      return "Summer"
   case Month.September, Month.October, Month.November
      return "Autumn"
   case Month.December, Month.January, Month.February:
      return "Winter"
   default:
      return "invalid"
}

3. Remove enumeration name

Since Swift is stronly-typed and uses type inference you can remove the enumeration name in places and keep the dot prefix and the compiler will knows the type, as shown below:

Swift Code :

func findSessions(_ month: Month) -> String{
   switch month {
   case .March, .April, .May:
      return "Spring"
   case .June, .July, .August:
      return "Summer"
   case .September, October, .November
      return "Autumn"
   case .December, January, .February:
      return "Winter"
   default:
      return "invalid"
}

4. Remove default case

Moreover, you can remove the default case when you use enumeration because enumerations have a limited set of value and it is impossible to be other type of value rather then Month and compiler will not warn you. Look back, if you case pattern is a String elements, then you need to have a default because there a infinite amount of value can be use.

Swift Code :

func findSessions(_ month: Month) -> String{
   switch month {
   case .March, .April, .May:
      return "Spring"
   case .June, .July, .August:
      return "Summer"
   case .September, October, .November
      return "Autumn"
   case .December, January, .February:
      return "Winter"
}

By using enumeration and removing the default as shown above. Your code become more clean and more readable. Another huge benefit is that, in the future, when someone add a new value to the enum, the compiler will flag this out that there are other Month enumeration in this switch statement as it is incomplete and you are require to handle it.

Raw Values

There is a problem here. For example, we want the extract the raw value of it which is "april" and thedata type is a Month.Type and not a String.Type. How can we do that?

Swift Code :

type(of: Month.april)

Output :

__lldb_expr_12.Month.Type

Enumeration allows you to link a default value or raw values. Take a look a the following example, when I specify an integer backs the enumerations by first declaring it with : datatype and then, you using an equal sign to assign the raw value to it like the example below. (Enumerations are flexible and you can specify any raw values types like Int, Float, Bool and etc).

Swift Code :

enum Month: String {
   case january = "january", february = "february", march = "march", april = "april", may = "may", june = "june", july = "july", august = "august", september = "september", october = "october", november = "november", december = "december"
}

1. Accessing the raw value

Enumeration come with a very handy rawValue property. Which allows you to use it like a normal String, Int, Float and etc.

Swift Code :

type(of: Month.april.rawValue)

Output :

String.Type

2. Initializing the raw value

Instead of using the dot notation (Month.april) to create the enumeration value. You can use the raw value to instantiate an enumeration value with an initializer. You can use init(rawValue: ). Remember, because we are submitting an raw value when you use it. There is a possible that you submitted a wrong raw value. Therefore, this initializer will return an optional. If thing go worng, it will return nil.

Look at the example, below, which require to force unwrap the optional in order to access the enum.

Swift Code :

let currentMonth = Month(rawValue: "january")
print( currentMonth! )

Output :

january

Associated Values