Enumerations
Enumerations (or otherwise known as enum) are a special data type that enables us to group-related types together and use them in a type safe manner. For those of us who are familiar with enums from other languages, such as C or Java, enums in Swift are not tied to integer values. The actual value of an enum (known as the raw value) can be a String, a Character, an Integer or a Floating-point value. Enums also support features that are traditionally supported only by classes such as computed properties and instance methods. We will discuss these advanced features in depth in classes and structures chapter. In this section, we will look at the traditional enum features.
We will define an enum
that contains the list of planets like this:
enum Planets { case Mercury case Venus case Earth case Mars case Jupiter case Saturn case Uranus case Neptune }
The values defined in an enum
are considered to be the member values (or simply the members) of the enum
. In most cases, you will see the member values defined like the preceding example because it is easy to read; however, there is a shorter version. This shorter version lets us define multiple members in a single line, separated by commas, like the following example shows:
enum Planets { case Mercury, Venus, Earth, Mars, Jupiter case Saturn, Uranus, Neptune }
We can then use the Planets
enum like this:
var planetWeLiveOn = Planets.Earth var furthestPlanet = Planets.Neptune
The type for the planetWeLiveOn
and furthestPlanet
variable is inferred when we initialize the variable with one of the member values of Planet
s. Once the variable type is inferred, we can then assign a new value without the Planets
prefix, like this:
planetWeLiveOn = .Mars
We can match an enum value using the traditional equals (==
) operator, or we could use a switch
statement. The following example shows how to use the equals
operator and the switch
statement with an enum:
if planetWeLiveOn == .Earth { println("Earth it is") } switch planetWeLiveOn { case .Mercury: println("We live on Mercury, it is very hot!") case .Venus: println("We live on Venus, it is very hot!") case .Earth: println("We live on Earth, just right") case .Mars: println("We live on Mars, a little cold") default: println("Where do we live?") }
Enums can come prepopulated with raw values, which are required to be of the same type. This means that we can define our enum to contain string, character, integer, or floating-point values, but all of the members must be defined as the same type. The following example shows how to define an enum with string values:
enum Devices: String { case iPod = "iPod" case iPhone = "iPhone" case iPad = "iPad" } println("We are using an " + Devices.iPad.rawValue)
The preceding example creates an enum
with three Apple devices. We then use the rawValue
property to retrieve the raw value for the iPad member of the Devices
enum. This example will print a message saying We are using an iPad
.
Let's create another Planet's enum, but this time, assign numbers to the members as follows:
enum Planets: Int { case Mercury = 1 case Venus case Earth case Mars case Jupiter case Saturn case Uranus case Neptune } println("Earth is planet number " + String(Planets.Earth.rawValue))
The big difference between the two enum
examples is that in the second example we only assign a value to the first member (Mercury
). If integers are used for the raw values of an enum, then we do not have to assign a value to each member. If no value is present, the raw values autoincrement.
In Swift, enums can also have associated values. Associate values allow us to store additional information along with member values. This additional information can vary each time we use the member. The additional information can also be of any type, and the types can be different for each member. Let's take a look at how we might use associate types by defining a Product
enum, which contains two types of products.
enum Product { case Book(Double, Int, Int) case Puzzle(Double, Int) } var masterSwift = Product.Book(49.99, 2015, 310) var worldPuzzle = Product.Puzzle(9.99, 200) switch masterSwift { case .Book(let price, let year, let pages): println("Mastering Swift was published in \(year) for the price of (price) and has \(pages) pages") case .Puzzle(let price, let pieces): println("Master Swift is a puzze with \(pieces) and sells for (price)") } switch worldPuzzle { case .Book(let price, let year, let pages): println("World Puzzle was published in \(year) for the price of (price) and has \(pages) pages") case .Puzzle(let price, let pieces): println("World Puzzle is a puzze with \(pieces) and sells for (price)") }
In the preceding example, we begin by defining a Product
enum with two members, Book
and Puzzle
. The Book
member has an associated value of Double, Int, Int,
and the Puzzle
member has an associated value of Double, Int
. We then create two products masterSwift
and worldPuzzle
. We assign the masterSwift
variable a value of Product.Book
with associated values of 49.99, 2015, 310
. We then assign the worldPuzzle
variable a value of Product.Puzzle
with associated values of 9.99, 200
.
We can then check the Products
enum using a switch
statement, as we did in some of the preceding enum examples. We also extract the associated values within the switch
statement. In the preceding example, we extracted the associated values as constants with the let
keyword, but you can also extract the associated values as variables with the var
keyword.
If you put the preceding code into a Playground, the following results will be displayed:
"Master Swift was published in 2015 for the price of 49.99 and has 310 pages" "World Puzzle is a puzze with 200 and sells for 9.99"