Leave a rating/review
Notes: 21. Enumerations
Update Notes: This course was originally recorded in 2019. It has been reviewed and all content and materials updated as of October 2021.
So, when I say “a specific set of related, discrete values.” What do I mean? Some commons examples are cardinal directions, colors, or card suits. State machines, like a traffic light, are also a great use case.
You could represent any of those with Strings or Integers. But it’s easy to misspell a String and numbers don’t map intuitively to any of them.
Enumerations help you avoid those problems with an explicit set of possible values. There are exactly four directions, 6 colors, four card suits, and three states a traffic light can be in.
If you followed along with the Your Second iOS & SwiftUI App course, you already used an enum to represent priority levels for a task! Let’s walk through some enumeration basics in a playground.
Months of the year are another great use case for an enumeration! To make an enumeration called Month, declare it like this:
enum Month {
}
It’s got a capital M, because enumerations are types, and types use UpperCamelCase by convention, in Swift. To specify the cases of the enum, use the keyword case, followed by the name of the case (in this case, a month)
case january
case february
You can also use a single case keyword followed by comma separated names, which is what we’ll do for Month:
case january, february, march, april, may, june, july, august, september, october, november, december
These cases are the only possible values for a Month to have. Notice that each case start with a lower case letter, just like a property or a function name.
To make a constant that is a Month, you can declare it two ways, but they’re very similar-looking. The implicit way is by assigning Month.october, for example.
let month = Month.october
If you option-click on the month constant, you can see that it is of type Month. *You can explicitly type it as well.
let month: Month = Month.october
Of course, that’s redundant-looking! With explicit typing involved, you can leave off the name of the enumeration, and start with the dot!
let month: Month = .october
In some other programming languages, enumeration values are all automatically backed by integers. That means they secretly have an Int value associated with the case.
That isn’t the way Swift works, though. october is the value of this constant.
But you can associate a raw value with each enumeration case simply by declaring the raw value type in the enumeration declaration:
enum Month😺: Int🛑 {
Just by doing that, if you don’t specify otherwise, Swift will automatically assign Int values to these cases, starting with 0 and going up.
But usually, we think of January as “month 1” and not “month 0”. To specify your own raw value, use the assignment operator
case january😺 = 1🛑,
If you still just want the other cases to increment themselves by 1 after that, you don’t need to specify the rest. February will be 2, march 3, and so on.
Now that each month has a raw Int value, we can do something like figure out how many months people should wait until it’s socially acceptable to sing Christmas songs.
func monthsUntilJingleBells(from month: Month) -> Int
}
That function will take in a Month and return an Int to represent the number of months. To access the raw value of an Enum case, use its rawValue property, like this:
Month.december.rawValue - month.rawValue
}
You are free to disagree with me about that equation, and set yours up however you like! But if you use a month other than December you may want to use a ternary operator or an if statement to return “0” when you get into negative numbers.
Regardless of what other month you chose, where I used december, we did need to use the type to get its value. But notice that because the function knows what type the month parameter is, we don’t need to add the type to it.
Now we can call that function, and pass in whatever month you like:
monthsUntilJingleBells(from: .november)
If it’s November, you still need to wait a month until you start with public performances of Jingle Bells. You can also initialize an enum case with a raw value, like this:
let rawMonth = Month(rawValue: 3)
But because the raw value you pass in might not exist, that will return an optional.So if you try to create enum instances that way, you’ll want to safely unwrap them before you use them.
String Raw Values
Let’s set up one more Enumeration! This one will be for seasons
enum Season
And we’ll give it String raw values
enum Season: String {
}
This time I’ll use the case keyword before every case, instead of comma-separating.
enum Season: String {
case winter
case spring
case summer
case autumn
}
What’s nice about that, is you can add documentation for each case individually. You do that with three slashes.
enum Season: String {
😺/// ☃️
case winter
😺/// 🌸
case spring
😺/// 😎
case summer
😺/// 🍂
case autumn
}
Then, when you’re using your enumeration,
Season.
…after a dot, you’ll see your documentation.
Season.winter
Normally, you’d probably want something a little more informative than an emoji, but any String will work!
There’s another magic automatic raw value thing happening here, for you. If you don’t specify the raw value, Swift will just use the name of the enumeration case. So, the raw value of “winter” would be…
Season.winter😺.rawValue
“winter”, as a String!
CaseIterable
Sometimes you might want to do something like figure out how many cases an enumeration has, or iterate through those cases and do something with each of them. You can absolutely do that, you just need to make your enumeration conform to the CaseIterable protocol.
enum Season: String😺, CaseIterable🛑 {
Now you can use the the allCases property on the type itself.
Season.allCases
We’ll talk more about protocols and type properties later in this course. But, allCases will give you an array containing all of the cases of the enumeration in the other they were declared.
Then you’re free to loop through them or use any of those fancy methods you learned like map or filter
Season.allCases😺.filter {
$0.rawValue.first == "s"
}🛑
Now you’ve got just the seasons that start with “s”! Enumerations are really powerful tools in Swift, and we’ve only scratched the surface. But before we do any more, try the next challenge!