Enums In Swift Explained

Enums In Swift Explained

Sometimes we need to create our own data types for certain parts of our app. That’s where Enumerations come in handy. But what are the other benefits of Enum?

The Swift Enum gives us the possibility to model a certain number of options, to make our code type-safe, error free and easy to use. Plus it’s extremely useful to have an Enumeration with a set of data which is never going to change. For instance with a deck of cards, weekdays, points of the compass and etc. We can even take a look at how the official Swift Programming Guide defines the enumeration.

A common type for a group of related values

The swift programming language

For the purpose of this tutorial, our code will be based on compass example. So we are going to have 4 different options: North, South, East, and West. To better understand the principle of Enumeration let’s go ahead and create one.

Ready? Let’s go.

An Enumeration Type Declaration

In order to start using the enumerations, we have to specify the enum keyword, followed by the name of the enumeration. The last step is to use curly braces and actually define the enum.

enum EnumerationName {
     // Enumeration definition 
}

Just like a boolean, which can only be set to true or false, we can set up a specific number of options for our custom type. Later any variable or constant that has the same data type has access to those options which we specified earlier. Now to make it more clear let’s take a look at the example.

enum Directions {
    case North
    case South
    case East
    case West
}


// Defining multiple cases on a single line

enum Directions { 
    case North, South, East, West 
}

In this case, our enum name is going to be Directions and inside the curly braces, we have specified 4 different cases. We have basically created our very first enumeration.

If you prefer you can also define multiple cases on a single line separated by a comma. It’s especially convenient when you would like to improve the readability of your code. 


Now when you want to specify a particular direction we can create a variable, which will represent the specific data type that we created earlier. Since every enumeration defines a new type it’s a good idea to start the Enum name with a capital letter. While following this principle our enumeration will always be self-evident.

var compass = Directions.North

// Shorter Syntax
compass = .West

In addition, we can simply access the different values inside our enumeration with dot syntax. The Swift type inference behavior provides information to the compiler that compass is of type Directions.

Enumeration Values and Switch Statement

In order to extend the functionality of our enumeration, we can use the Switch statement. So instead of having just different directions on our digital compass, we will also provide some additional information. Let me show you how. 

enum Directions {
    case North
    case South
    case East
    case West
}

var digitalCompass: Directions = Directions.North

switch digitalCompass {
case .North: "You are on the right track"
case .South: "You are travelling in the wrong direction"
case .East: "You should turn right"
case .West: "You should turn left"
}

First of all, we declare the variable “digitalCompass” which has the direction “North”. In order to provide a little message in the console, we can use a switch statement. So whenever the direction changes we give the users a certain update on the screen. 

The great thing about switch statement is that we can simply write “.North” instead of “Directions.North” which is really convenient. The reason is that “digitalCompass” is of type Directions. Also for this switch statement, we omit the default case since one of these cases is guaranteed to be true.

You might be thinking this is a great way setting this up but there is actually a better way. With Enums we can take this a little bit further.

Associated Values

A huge benefit of Swift Enums is that they are not secretly Ints, so we can associate more values with each case. Simply because knowing which state we’re in is not always enough. So this feature will provide some additional information associated with each state.

In addition to the enum name, we need to provide the Associated Value as well. The Associated values are not exposed as properties instead, we use a let/var in the switch case to extract the value.

enum Directions {
    case North(String)
    case South(latitude: Double, longitude: Double)
    case East(String)
    case West(String)
}

var digitalCompass1 = Directions.North("You are on the right track")
var digitalCompass2 = Directions.South(latitude: -120.83, longitude: 37.0)
digitalCompass1
digitalCompass2


// Prints:

North("You are on the right track")

South(latitude: -120.83, longitude: 37.0)

In our case, we can use this feature to associate different value for each case in our enumeration. For instance, we can specify the message for the user in the case of “North”. However, for the “South” we can be more descriptive and provide the exact coordinates, including latitude and longitude. While defining the associated values we are not providing the actual values. The information can be assigned to different coordinates once we create a new variable.

Now to extract the values we have to use the switch statement. In addition, we can take advantage of constants and variables to store different data inside our switch statement

enum Directions {
    case North(String)
    case South(Double, Double)
}

var digitalCompass1 = Directions.North("You are on the right track")
var digitalCompass2 = Directions.South(-120.83, 37.0)


switch digitalCompass1 {
case .North(let currentDirection):
    print(currentDirection)
case .South:
    print("Compass is static")
}

switch digitalCompass2 {
case .North(let currentDirection):
    print(currentDirection)
case .South(let latitude, let longitude):
    print("Your coordinates are: \(latitude), \(longitude)")
}


// Prints:

You are on the right track 
Your coordinates are: -120.83, 37.0

Raw Values

Raw values gives us the possibility to specify some behavior for every single case in the enumeration. First, we specify that in Directions every raw value is going to hold a String. After that, we store those messages directly into the Enum. That way we basically recreate the same functionality as we did in the switch statement.

enum Directions: String {
    case North = "You are on the right track"
    case South = "You are travelling in the wrong direction"
    case East = "You should turn right"
    case West = "You must turn left"
}

var digitalCompass: Directions = Directions.North
digitalCompass.rawValue

Now we can create the same variable called “digitalCompass” and specify it’s direction to be “North”. More importantly, we can even access it’s raw-value. So basically we are asking the compiler the following question: “I know that my coordinate is North, but what is the value of North?”

Implicit Raw Value Assignment

While working with enumerations you don’t always have to explicitly specify the values. In this example, we are going to take a look at how Swift can automatically assign raw values to different cases.

enum Directions: Int {
    case North = 1, South, West, East
}

var compass1 = Directions.North
var compass2 = Directions.South
var compass3 = Directions.West
var compass4 = Directions.East 
 
compass1.rawValue
compass2.rawValue
compass3.rawValue
compass4.rawValue  


// Prints:

1
2
3
4

In the following example, we have only assigned a raw value to “North” but other cases will also receive a value. If the first case doesn’t have any initial value then it will be equals to 0. Plus the raw value of every next case will be incremented by 1.

So the main power of raw value is that it allows you to immediately associate the particular case with a specific data we need to use.

Further Reading

Enumerations are a really great solution when you want to create your own data types. Especially when there are a specified number of options available.

Since enumerations are a bit confusing, don’t hesitate to ask any questions. But remember: If you practice, everything will make much more sense.