Welcome to the second tutorial in this quick start guide to Swift. We’ll cover some of the concepts from the first part in more detail while also introducing more language features.

What you will learn…

  • More detail regarding strings
  • How to work with arrays and dictionaries
  • Control flow with while loops and the switch statement
  • How to work with enumerations

What you should know…

  • A familiarity with at least one programming language
  • The basics of the Swift programming language from part one

The primary focus of part two will be strings, collection types, control flow, and enumerations. We briefly looked at strings in part one but will spend more time with them here. We’ll also re-visit control flow, taking the time to examine while loops, do-while loops, and Swift’s powerful switch statement. You may have noticed that arrays weren’t covered in part one. We’ll make up for that here and also focus on Swift’s other collection type: dictionaries. Finally we’ll round off part two by covering enumerations.

ECMAScript developers following this series will discover that most of what is covered here isn’t that dissimilar to the features found in languages such as JavaScript and ActionScript. Enumerations being really the only exception for some of you. For those from a C programming background, everything will feel familiar, although you may be surprised at the additional power and flexibility that Swift brings to many of these features.

As stated previously, everything covered in this series of tutorials can also be found in Apple’s own official guide to the Swift programming language. The intention here however is to focus on the elements of the language that are required to get newcomers up and running as quickly as possible. If you have the time and want the full detail then I highly recommend you head straight over to Apple’s Swift Programming Language Guide instead.

Getting Started

If you haven’t worked your way through the first tutorial in the series then I recommend you start from there.

You should also consider installing Xcode 6 and creating a playground to try out his tutorial’s various code examples. Detail regarding that can be found in the first tutorial.

More on Strings

We briefly looked at strings in the first tutorial. Let’s revisit them and get some more detail.

The String type represents a collection of ordered values of type Character. Swift’s String and Character types are fully Unicode-compliant. As discussed previously, a string literal can be used to initialise your variables and constants:

let jedi = "Luke Skywalker"

It’s also possible to create a string that is initially empty:

var playerName = ""

You can also check whether a string is empty:

if playerName.isEmpty {
  playerName = "anonymous"
}

The “equal to” operator (==) is used to determine if two strings are equal:

let person1 = "Christopher"
let person2 = "Christopher"
if person1 == person2 {
  println("Both people share the same name.")
}

The addition (+) operator can be used to concatenate strings:

var forename = "Luke"
var surname = "Skywalker"
var name = forename + " " + surname

Only string variables can be changed after they are initialised. Once a string constant has been set, it cannot be altered. The following example will result in a compile-time error:

let name = "Anakin Skywalker"
name = "Darth Vader"

Characters

As stated, a string is an ordered collection of characters. You can access each of a string’s characters with a for-in loop. Here’s an example:

let sith = "Darth"
for c in sith {
  println(c)
}

This will result in the following being output:

D
a
r
t
h

In order to see the results of a loop within your playground you’ll need to take advantage of the timeline assistant. To do this, look in the sidebar, directly along from your loop’s println() call. You should see the text (5 times) and an icon of a dot to the right of that.

timeline-assistant

If you click that icon, the timeline assistant pane will open and you’ll be able to see the result from each iteration of your loop.

In the code example above, the c variable will hold a single character at any one time and is therefore of type Character.

As with strings, the “equal to” operator (==) is used to check if two characters are equal:

let character1: Character = "c"
let character2: Character = "c"
if character1 == character2 {
  println("Both characters are the same.")
}

Notice that the Character type had to be explicitly declared to prevent both variables from being inferred as String types. There is no single-quote syntax for character literals in Swift.

It’s not possible to check the equality of a String against a Character without first converting the character to a String type. Here’s an example:

let myCharacter: Character = "c"
let myString = "c"
if String(myCharacter) == myString {
  println("Both characters are the same.")
}

You can append a Character value to a String with the append() method. Here’s an example:

var greeting = "Hullo"
let exclamationMark: Character = "!"
greeting.append(exclamationMark)

You can obtain the number of characters in a string by using the global count() function:

var jedi = "Luke Skywalker"
var numberOfCharacters = countElements(jedi)
println(numberOfCharacters)

The above example will output 14.

Playground Experiment
Create two constants. Set the first to hold your forename and the second to hold your surname. Concatenate both constants and hold the result in a variable called fullname. Finally check the number of characters stored within your fullname variable. If it’s over 15 characters in length then print The name is too long. to the appropriate output. Otherwise, simply print your full name.

String Interpolation

We’ve already utilised string interpolation when working with the global println() function. String interpolation allows you to insert variables, constants, literals, and expressions as placeholders directly within a string. This is done by wrapping each item in parentheses and escaping them with a backslash before the opening parenthesis. Here’s an example:

let name = "Luke Skywalker"
var kills = 64
let pointsPerKill = 10
let message = "\(name) scored a total of \(kills * pointsPerKill) points"

This will result in a message variable that contains the string value: Luke Skywalker scored a total of 640 points.

Character Indexing

The internal Unicode representation of strings in Swift means that random access of a string’s individual Character values via integer indexing is not supported. For example, you may reasonably expect the following to work:

let pilot = "Wedge"
let lastCharacter = pilot[4]

Instead you need to query a string for its starting index and then use the global advance() function to move to the desired position within the string. Here’s the previous example rewritten:

let pilot = "Wedge"
let index = advance(pilot.startIndex, 4)
let lastCharacter = pilot[index]

This will result in the lastCharacter constant being assigned a value of e. It’s important to note that the index constant above is not of type Int. Instead it’s a String.Index opaque type, which Swift’s character and range indices are based on.

Playground Experiment
Alter the previous experiment’s code to print out a truncated version of your full name if it’s over 15 characters in length. The name should end with an ellipsis to indicate that it has been truncated. For example, the name Christopher Caleb would be displayed as Christopher Cal....

Arrays

Arrays are one of two collection types supported by Swift (Dictionaries being the other). Each element within a Swift array must be of the same type.

This is different from languages such as JavaScript, ActionScript, and even Objective-C, where each element can be of a different type.

Initialising Arrays

An array can be declared and initialised with an array literal. Here’s an example:

var droids: [String] = ["c3p0", "r2d2"]

This creates an array that initially contains two strings: "c3p0" and "r2d2". Of course, thanks to Swift’s type inference we can actually shorten the above example to:

var droids = ["c3p0", "r2d2"]

An immutable array can be created by using a constant instead of a variable:

let droids = ["c3p0", "r2d2"]

In the example above, the array cannot be altered after it’s initialised. By assigning your array to a variable instead, you’ll be free to add, remove, or change values stored within it.

You can create an empty array of a specified type with the following:

var droids: [String] = []

Or alternatively by using Swift’s initializer syntax:

var droids = [String]()

There’s also an initializer for creating an array of a certain size and populating it with a provided default value. The following creates an array of 100 integers, with each initialised to 64:

var myArray = [Int](count: 100, repeatedValue: 64)

Accessing and Modifying an Array

Swift uses subscript syntax and zero-based indexing to obtain and modify the value of items within an array. Here’s an example that changes an array’s 5th item from 1500 to 2000:

var scores = [100, 200, 500, 1000, 1500]
scores[4] = 2000

The following example obtains the value of the first item within the array:

var scores = [100, 200, 500, 1000, 1500]
var lowestScore = scores[0]

Subscript syntax can even be used to replace a range of values within an array:

var topFriends = ["Bob", "James", "Jane", "Elizabeth", "Amanda"]
topFriends[0...2] = ["Christopher", "Alan", "Freddy"]

This will replace the first three strings within the topFriends array with “Christopher”, “Alan”, and “Freddy”.

You can add a new item to the end of an array with the append() method:

var droids = ["c3p0", "r2d2"]
droids.append("r5d5")
println(droids)

The code example above will output [c3p0, r2d2, r5d5].

It’s also possible to append an array of compatible values to an existing array. This is done with the addition assignment operator (+=):

var droids = ["c3p0", "r2d2"]
droids += ["r5d5", "ig88", "tc14"]
println(droids)

The example above will print [c3p0, r2d2, r5d5, ig88, tc14] to the appropriate output.

Swift provides an insert(atIndex:) method, which inserts an item at the specified index:

var bestScores = [10, 50, 100, 500]
bestScores.insert(150, atIndex:3)
println(bestScores)

This will insert a value of 150 immediately after 100 in the array. The final output will be: [10, 50, 100, 150, 500].

You can remove an item at a specific index with the removeAtIndex() method:

var bestScores = [10, 50, 100, 500]
bestScores.removeAtIndex(1)
println(bestScores)

This will remove the second item from the array and print the following: [10, 100, 500].

You can obtain the number of items in an array via its count property:

var jedi = ["Skywalker", "Kenobi", "Yoda", "Windu"]
let numberOfJedi = jedi.count

Playground Experiment
Write a program that takes an array of integers and sorts them in ascending order. The sorted list should be printed to the appropriate output. For example, if you were to start off by initialising a variable that held the following values: 20, 40, 10, 5, 200, 145, 5. Then your program should display those values in the following order as its final result: 5, 5, 10, 20, 40, 145, 200.

Accessing Outside An Array’s Bounds

A runtime error is triggered if you attempt to obtain or set a value for an index that is outside an array’s bounds. For example:

var jedi = ["Skywalker", "Kenobi", "Yoda", "Windu"]
let name = jedi[64]
println("Name: \(name)")

This will result in a runtime error since we’re trying to access the 65th string within an array that only contains four values.

Before accessing or modifying a value within an array you should use its count property to determine whether the index position you are using is valid:

var jedi = ["Skywalker", "Kenobi", "Yoda", "Windu"]
var index = 64
if index < jedi.count {   let name = jedi[index]   println("Name: \(name)") }

The example above avoids the risk of a runtime error. It’s also worth remembering that array indexes are zero-based in Swift. You should take that into account when using an array’s size to determine if an index position is within bounds.

Iterating Over an Array

You can use a for-in loop to iterate over an array:

var jedi = ["Skywalker", "Kenobi", "Yoda", "Windu"]
for name in jedi {
 println(name)
}

The code snippet above will print the following to the appropriate output:

Skywalker
Kenobi
Yoda
Windu

You can also take advantage of Swift’s global enumerate() function to extract the value and index position of each item into a tuple. Here’s how:

var jedi = ["Skywalker", "Kenobi", "Yoda", "Windu"]
for (index, name) in enumerate(jedi) {
  println("\(index): \(name)")
}

This will result in the following being output:

0: Skywalker
1: Kenobi
2: Yoda
3: Windu

Dictionaries

Unlike arrays, dictionaries do not store items in a specified order. Instead, each item added to a dictionary is associated with a unique key, which acts as an identifier for that item. All items added to a dictionary must be of the same type. The same is true for the unique keys you use also.

When working with dictionaries in Swift, you have to be specific about the type you’ll use for your keys, and the type you’ll use for your values. This is different from languages such as JavaScript, ActionScript 3, and even Objective-C, where you can use a different type for each key and each value if you wish.

Let’s look at a simple example:

var scores: [String: Int] = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]

We have a dictionary of player scores. Each player’s name is used as a key, and there is a score associated with each key. The keys are of type String and the values are all of type Int. In other words, we have declared a dictionary that has a type of [String: Int].

Since we initialised our scores dictionary with a literal we can let Swift infer the dictionary’s type for us. So we can shorten our original example to this:

var scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]

An immutable dictionary can be created by using a constant instead of a variable:

let scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]

You can create an empty dictionary of a specified type with the following:

var scores: [String: Int] = [:]

Or alternatively by using Swift’s initializer syntax:

var scores = [String: Int]()

Accessing and Modifying a Dictionary

Subscript syntax is used to access or modify an existing value within a dictionary. Here’s an example of a value being modified:

var scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]
scores["Freddy"] = 20000

A little more effort is required to access a value. It’s possible that the key you use with your subscript may not actually have an associated value within the dictionary:

var scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]
let score = scores["Bob"]

As you can see from the example above, the key Bob doesn’t actually exist within the dictionary. When this is the case, nil will be returned. If you think back to the first tutorial in the series, you’ll remember that variables and constants in Swift cannot be nil and must always have a value associated with them. To get around this constraint, Swift provides optionals, which can either have a value or no value at all (nil).

That means that in the example we just looked at, the dictionary’s subscript is actually returning an optional rather than the value that’s directly associated with the key. Once you’ve determined that the optional retrieved from the dictionary isn’t nil, you’ll need to unwrap it (place an exclamation mark at the end of the optional’s name) to retrieve its value. Here’s a concrete example:

var scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]
let score = scores["Bob"]
if score != nil {
  println("Bob’s score is: \(score!)")
} else {
  println("There is no score for Bob")
}

As an alternative to using an if statement before obtaining an optional’s value, you can also use optional binding. Here’s the above example re-written:

var scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]
if let score = scores["Bob"] {
  println("Bob’s score is: \(score)")
} else {
  println("There is no score for Bob")
}

Playground Experiment
Create a dictionary that holds the following characters from the Star Wars movies and a force rating for each:

Skywalker 100
Kenobi    120
Maul      80
Vader     90
Yoda      1000
Windu     110
Emperor   200

Given the following array of names ["Maul", "Vader", "Emperor"], write a program that finds each character’s rating and prints it to the screen along with their name.

Subscript syntax can also be used to add new items to a dictionary:

var scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]
scores["Christopher"] = 50000

The code snippet above adds a new key named Christopher and associates a value of 50000 with it.

You can obtain the number of items in a dictionary via its count property:

var scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]
let numberOfScores = scores.count

Iterating Over a Dictionary

You can use a for-in loop to iterate over a dictionary:

let scores = ["Amanda": 10000, "Alan": 8000, "Freddy": 1000]
for (name, score) in scores {
  println("\(name): \(score)")
}

In the above example, each item in the dictionary is returned as a (key, value) tuple. The tuple’s members are decomposed into constants called name and score, then printed to the appropriate output as:

Amanda: 10000
Alan: 8000
Freddy: 1000

It’s possible to retrieve a collection of keys or values from a dictionary via its keys and values properties. You can then iterate over your collection using a for-in loop. Here’s an example that iterates over the keys from our scores array:

for name in scores.keys {
  println("Name: \(name)")
}

You can also initialise a new array with either your collection of keys or collection of values. Here’s an example:

let scoresArray = [Int](scores.values)

Note from the example above that the your array’s type needs to match the type of the values stored within your dictionary.

It’s important to remember that items within a dictionary have no specific order. In other words, you can’t be guaranteed that keys, values, or key-value pairs will be retrieved in any specific order when attempting to iterate over a dictionary.

Playground Experiment
Create a dictionary that holds the following names and scores:

Christopher 10000
Alan        8000
Amanda      2500
Elizabeth   120
Freddy      11050
Helen       60
Cheryl      30

Write a program that iterates over your dictionary and displays the names of those who have scored over 5000 points. Also display each person’s score alongside their name.

While Loops

Swift provides the familiar while and do-while loops. Let’s take a look at the while loop.

While Loop

The general structure of a while loop isn’t difficult to grasp. Here’s an example:

var index = 0
while index < 5 {   println("index: \(index)")   index++ }

As with the for loop (from part one), parentheses aren’t required in Swift. The code above will result in the following output:

index: 0
index: 1
index: 2
index: 3
index: 4

The while loop starts by evaluating its condition. If the condition is true, the loop’s block of statements is repeated until the condition becomes false. In the case of our example, the loop continues until the index variable no longer has a value less than 5.

Do-While Loop

The do-while loop is a variation of the while loop. It performs a single pass of the loop’s block of statements before evaluating the loop’s condition. Here’s the previous example rewritten to use a do-while loop:

var index = 0
do {
  println("index: \(index)")
  index++
} while index < 5

The major difference between both variations is that the do-while loop will always execute the statements within its block at least once, whereas a while loop’s block may not execute at all if its condition initially evaluates to false.

Don’t forget about block scope. Variables and constants declared within while and do-while loops are only valid within the scope of each loop.

Switch Statement

Swift’s switch statement is extremely powerful. At a glance it may not look that different from the switch statement provided by other languages. Take this simple example as a starting point:

var name = "Dooku"
switch name {
case "Skywalker":
  println("\(name) is a Jedi")
  break
case "Kenobi":
  println("\(name) is a Jedi")
  break
case "Vader":
  println("\(name) is a Sith")
  break
case "Dooku":
  println("\(name) is a Sith")
  break
default:
  println("I don’t know if \(name) is a Jedi or Sith")
}

Running this within your playground will result in Dooku is a Sith being displayed in the sidebar. More or less as you’d expect, right?

If you’re an Objective-C developer then you’ll be delighted to see from the above example that you can switch on strings. While developers of ECMAScript-based languages have always been able to do this, Objective-C’s roots meant that its switch statement had all the hangups of the C programming language.

Our current example uses a break statement at the end of each case. However this isn’t required since switch statements in Swift do not automatically fall through to the next case. In other words, we can (and should) rewrite our example with the break statements removed:

var name = "Dooku"
switch name {
case "Skywalker":
  println("\(name) is a Jedi")
case "Kenobi":
  println("\(name) is a Jedi")
case "Vader":
  println("\(name) is a Sith")
case "Dooku":
  println("\(name) is a Sith")
default:
  println("I don’t know if \(name) is a Jedi or Sith")
}

It should also be noted that switch statements in Swift should be exhaustive. What I mean by that is, there should be a matching case statement for every possible value. Where that isn’t feasible, the default keyword should be used to provide a catch-all.

Playground Experiment
To verify this, try removing the default statement at the end of our current example. You’ll receive the following error within your playground:

Switch must be exhaustive, consider adding a default clause

Before continuing, add the default case back into your code example.

Looking at our example again, you should notice that the first and second cases produce the same result. The same is also true of the third and fourth cases. You may be tempted to re-factor your switch statement like this:

var name = "Dooku"
switch name {
case "Skywalker":
case "Kenobi":
  println("\(name) is a Jedi")
case "Vader":
case "Dooku":
  println("\(name) is a Sith")
default:
  println("I don’t know if \(name) is a Jedi or Sith")
}

This code will fail to compile for two reasons. First, as discussed, Swift’s Switch statement does not fall through to the next case by default. Secondly, in Swift, the body of each case must contain at least one executable statement.

To get around this problem, Swift lets you write a comma separated list of matches for a single case. Here’s how the previous code example should be written:

var name = "Dooku"
switch name {
case "Skywalker", "Kenobi":
  println("\(name) is a Jedi")
case "Vader", "Dooku":
  println("\(name) is a Sith")
default:
  println("I don’t know if \(name) is a Jedi or Sith")
}

We currently print a message if a match is not found for the value of the name variable. What if, by design, nothing was to be printed when there was no match? While the use of the break statement is discouraged, it actually comes in handy for situations such as this:

var name = "Dooku"
switch name {
case "Skywalker", "Kenobi":
  println("\(name) is a Jedi")
case "Vader", "Dooku":
  println("\(name) is a Sith")
default:
  break
}

Explicit Fallthrough

As has just been discussed, switch statements in Swift do not automatically fall through the bottom of each case and into the next one. Therefore there’s no need to explicitly place a break statement at the end of each case since the execution of your switch statement will terminate as soon as the first matching case is completed.

But what if you actually had a need to drop through to the next case? Swift allows you to do that so long as you’re explicit about it. This prevents the common programming errors you see in other languages where execution dropped through to the switch statement’s next case by accident. The fallthrough statement is used for such situations. Here’s our previous example re-written to use it:

var name = "Dooku"
switch name {
case "Skywalker":
  fallthrough
case "Kenobi":
  println("\(name) is a Jedi")
case "Vader"
  fallthrough
case "Dooku":
  println("\(name) is a Sith")
default:
  break
}

While the code snippet does technically work, it has been contrived in order to illustrate how the fallthrough statement works. If you find yourself writing code like this then you really should consider ditching the fallthrough statement and created comma separated lists of matches for each case instead.

Range Matching

This is where things get interesting. Swift allows the value in a switch statement to be checked against a range. Here’s our if-else code example from part one, but this time using a switch statement:

var energy = 40
switch energy {
case 0:
  println("Vader’s lightsaber cuts through you.")
case 1...20:
  println("Your powers are weak old man.")
case 21...40:
  println("You have much to learn.")
default:
  println("The force is strong with you.")
}

The example above would result in You have much to learn. being printed to the appropriate output.

We only see the use of the closed range operator (a...b) here, but the half-open range operator (a..<b) can obviously be used too.

Tuples

Tuples can also be matched in a switch statement, giving you greater pattern matching capabilities. Here’s a simple example that recognises types of iOS devices:

let currentScreen = (width: 640, height: 1136)
switch currentScreen {
case (768, 1024):
  println("A non-Retina iPad")
case (1536, 2048):
  println("A Retina iPad")
case (320, 480):
  println("A non-Retina iPhone")
case (640, 960), (640, 1136), (750, 1334), (1080, 1920):
  println("A Retina iPhone")
default:
  println("Unknown iDevice")
}

This would print A Retina iPhone to the appropriate output.

As discussed in part one, you can use an underscore to ignore values within a tuple that you aren’t interested in. In addition, it’s also possible to use the two range operators when specifying matching tuples:

let player = (energy: 10, level: 25)
switch player {
case (0, _):
  println("Game Over!")
case (1..<10, _):   println("Energy Low!") case (_, 5...10):   println("Keep up the good progress") case (_, 11...25):   println("Awesome! Keep going!") default:   println("Doing fine") }

In the above code example, a player’s status is printed based on their current energy and the game level they have reached. The player’s health is regarding as being of greater importance, so a message related to their energy will take priority.

This is handled by the first two case statements, with an underscore used to ignore the player’s current level. The next two are more concerned with the player’s level progress, with an underscore being employed to ignore the player’s energy value. Also notice the use of the closed range and half-open range operators throughout the switch statement’s cases.

Running the above code within your playground would result in Awesome! Keep going! being displayed in the sidebar.

With these relatively simply examples, we’re seeing more complex pattern matching capabilities available with Swift’s switch statement compared to languages such as Objective-C or more high-level languages such as JavaScript.

Value Binding

The values a switch case matches can be bound to temporary constants or variables. These constants and variables can then be used within the case’s body. Here’s an example:

let player = (energy: 15, level: 100)
switch player {
case (0, let level):
  println("Game Over! You reached level \(level).")
case (let energy, 100):
  println("You completed the game with a health of \(energy).")
case let (energy, level):
  println("You are on level \(level) with a health of \(energy).")
}

This would result in You completed the game with a health of 15. being output to your playground’s sidebar.

Where

Finally, a where clause can be used in a switch statement’s case to check for additional conditions. Here’s the previous example with a few more conditions added:

let player = (energy: 5, level: 90)
let enemyCount = 50
switch player {
case (0, let level):
  println("Game Over! You reached level \(level).")
case (let energy, 100):
  println("You completed the game with a health of \(energy).")
case let (energy, level) where enemyCount > 25 && energy < 10:   println("You are being swamped by the enemy and are close to death.") case let (energy, level) where enemyCount > 25:
  println("You are being swamped by the enemy! Do something!")

case let (energy, level):
  println("You are on level \(level) with a health of \(energy).")
}

The above example would result in You are being swamped by the enemy and are close to death. being sent to the appropriate output.

Notice that our code example introduces a constant named enemyCount, which appears in both usages of the where clause. The first where clause also uses a temporary energy constant that is bound to the first tuple value matched by its associated case.

Playground Experiment
We have a 2D Cartesian coordinate system that has a square and a rectangle placed on it. The square’s top-left corner is at (-2, -2) and its bottom-right corner is at (2, 2). The rectangle’s top-left corner is at (-4, -10) and its bottom-right corner is at (4, 10).

Write a program that takes an (x, y) point and provides feedback as to where that point is. If the point is at the origin then print Is at the origin to the appropriate output. If the point is within the square then print Within the square. If the point is within the rectangle then print Within the rectangle. If the point is lying somewhere along the x-axis then print On the x-axis. If the point is lying somewhere on the y-axis then print On the y-axis. For any other position, then display Somewhere else.

Use a tuple to define the point and take advantage of Swift’s switch statement to determine the point’s position. Test you code with a few locations such as (0, 0), (1, 1), (3, 6), (0, 20), (20, 0), and (40, 70).

I hope you can see from these examples just how powerful Swift’s switch statement can be.

Enums

If you’re from a JavaScript or ActionScript background then you may not be familiar with enumerations. If, on the other hand, you’re familiar with Objective-C or other similar languages then you’ll be pleasantly surprised by the flexibility of enumerations in Swift.

So what is an enumeration? Put simply, an enumeration is a type that represents a group of related values. For example, you may want to create a type that represents the days of the week, or a type that represents the months in a year. Another example could be a type that represents the four points of a compass.

Let’s use the days of the week as a concrete example:

enum Day {
  case Monday
  case Tuesday
  case Wednesday
  case Thursday
  case Friday
  case Saturday
  case Sunday
}

In the example above we have defined an enumeration type named Day that contains the days of the week (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, and Sunday) as its members.

The case keyword was used to declare each member of the enumeration. It’s also possible to comma separate our members on a single line.

Here’s an alternative way of declaring our enumeration:

enum Day {
  case Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}

Now that our Day enumeration type has been created, lets see how to use it:

var today = Day.Saturday

We’ve just created a variable named today that is set to the member Saturday from our enumeration. The today variable’s type has been inferred by the fact that it has been initialised with one of the values from Day. Once the variable has been initialised, you can use a shorthand syntax to set it to a different value belonging to the enumeration:

today = .Sunday

Of course, the following is also valid, but the shorthand syntax used above is preferred:

today = Day.Sunday

Conditional Statements

As you might expect, an enumeration can be used with if statements and switch statements. Let’s start with a simple example that makes use of the if statement:

var today = Day.Wednesday
if today == .Wednesday {
  println("Swimming lessons today")
}

The code snippet above will print Swimming lessons today to the appropriate output. Once again, notice the use of the shorthand syntax (.Wednesday rather than Day.Wednesay) within the if statement’s condition.

Now let’s take a look at a more sophisticated example that takes advantage of the switch statement:

var today = Day.Saturday
switch today {
case .Monday, .Tuesday, .Wednesday, .Thursday, .Friday:
  println("Work today")
case .Saturday, .Sunday:
  println("It’s the weekend!")
}

Adding the following to your playground file would result in It's the weekend! being displayed within the sidebar.

It’s also worth noting that the default statement wasn’t used in our switch statement. There was no need to because an exhaustive list of all possible enumeration values was provided.

Playground Experiment
Rock-paper-scissors is a game where two players simultaneously form one of three shapes with their hand. The “rock” beats scissors, the “scissors” beat paper, and “paper” beats rock. If both players throw the same shape then the game is tied.

Write a small program that plays out a single game of Rock-paper-scissors.

Declare an enumeration named Shape that contains the game’s three shapes: rock, paper, and scissors.

Declare two constants named player1 and player2 to hold each player’s chosen shape.

Finally, use an if statement to handle the logic to determine which player has won. You’ll also need to handle a tie situation. If player one wins then Player 1 wins should be displayed. If player two wins then display Player 2 wins. In the event of a tie situation, The game is tied should be output.

Test your code by setting different values for your player1 and player2 constants.

Raw Values

In programming languages such as Objective-C, each of an enumeration’s members is assigned an integer value, typically starting from 0 and being incremented for each subsequent member. In Swift, each member is a value in its own right and does not require an integer to be assigned to it. However, you can assign an integer (or any other type) to each member if you so require. These values are known as raw values and must all be of the same type.

Let’s take a look at an example where we use an integer to stipulate an order for our days of the week:

enum Day: Int {
 case Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5,
      Saturday = 6, Sunday = 7
}

Notice that we assign a value of 1 to our first member, then increment that value by one for each subsequent member. Doing so isn’t a requirement. We can assign any arbitrary value to our members. However, if we do wish to apply an incremental sequence of integers to each of our members then we only need to assign a default value to the first member and the remaining values will be inferred:

enum Day: Int {
  case Monday = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}

You can obtain a member’s raw value with its rawValue property:

let position = Day.Wednesday.rawValue
println("Today’s position within the week is: \(position)")

This would result in Today's position within the week is: 3 being sent to the appropriate output.

It’s also possible to find an enumeration’s member based on a raw value. Your enumeration will automatically have an initializer that you can take advantage of. Here’s an example:

let positionToFind = 3
if let day = Day(rawValue: positionToFind) {
  if day == .Wednesday {
    println("Swimming lessons today")
  } else {
    println("Not up to anything today")
  }
}

The initializer returns either an enumeration member or nil if a member doesn’t exist for the specified raw value. In other words, it returns an optional enumeration member. Since we are dealing with an optional in our example above, optional binding is used to ensure that we aren’t inadvertently working with a variable whose value is nil.

The example above will result in Swimming lessons today being printed to the appropriate output.

Associated Values

We’ve just seen how the members of an enumeration can be pre-populated with raw values. As an alternative you can also associate a value with an enumeration’s member. The distinction between the two is that a raw value is fixed to a specific member, whereas an associated value can vary every time you use that member.

As an example, let’s consider an enumeration that’s used to represent the status of a construction project. The construction can be either on time, or delayed. Here’s how that may be represented:

enum ConstructionStatus {
  case OnTime
  case Delayed
}

With this we can easily create a variable that specifies that a construction project is delayed:

var deathStarConstructionStatus = ConstructionStatus.Delayed

However, we can actually declare a better enumeration that can store information detailing how many months a construction is actually delayed by. Here’s an improved version of our enumeration:

enum ConstructionStatus {
  case OnTime
  case Delayed(Int)
}

The Delayed member now has an integer value associated with it, and that value can be used to store how long (for example, in months) the project has been delayed for. Let’s take a look at how to use it:

var deathStarConstructionStatus = ConstructionStatus.Delayed(6)

The line above states that construction is six months behind.

If at any point, there are further delays then the variable can be updated:

deathStarConstructionStatus = .Delayed(7)

We can use a switch statement to check for either of the enumeration’s members, and also match against any associated values that may belong to them. Here’s a complete example using our ConstructionStatus enumeration type:

enum ConstructionStatus {
  case OnTime
  case Delayed(Int)
}

var deathStarConstructionStatus = ConstructionStatus.Delayed(7)

switch deathStarConstructionStatus {
case .OnTime:
  println("The Death Star is complete. The Emperor is pleased.")
case .Delayed(0...3):
  println("Construction is slightly behind schedule.")
case .Delayed(4...6):
  println("Construction is behind schedule.")
default:
  println("The Emperor is most displeased.")
}

Not only are we seeing the flexibility of enumerations within Swift, we’re also once again seeing just how powerful Swift’s switch statement is. In our code above, we can see the closed range operator being used to specify a case where construction is between 0 and 3 months behind, and another case where construction has been delayed between 4 and 6 months.

It’s also possible to extract the value associated with an enumeration’s member. Here’s the above example re-written to display the actual number of months the project is delayed by if it is already seven months late or more:

enum ConstructionStatus {
  case OnTime
  case Delayed(Int)
}

var deathStarConstructionStatus = ConstructionStatus.Delayed(7)

switch deathStarConstructionStatus {
case .OnTime:
  println("The Death Star is complete. The Emperor is pleased.")
case .Delayed(0...3):
  println("Construction is slightly behind schedule.")
case .Delayed(4...6):
  println("Construction is behind schedule.")
case .Delayed(let months):
  println("Construction is \(months) months behind. " +
    "The Emperor is most displeased.")

}

I hope you can see the benefit of using Swift’s enumerations. While we’ve spent significant time with enumerations, there’s actually still a lot more to learn. For example, enumerations support many of the features that are traditionally only associated with classes including instance and static methods, but we’ll leave that for another day.

Next Time

Once again we’ve covered a significant amount of ground. There’s plenty to digest so please spend as much time as possible experimenting within a playground until you’re confident you fully understand everything. That goes for many of the language features (optionals, tuples, range operators, etc) from part one that were utilised in this second tutorial.

In part three we’ll start by looking at functions before moving on to structures. Structures share many of the same features as classes, and are therefore a good place to start before exploring Swift’s object-oriented features.

I’d like to reiterate the message from last time. There really isn’t anything particularly difficult about the basics of Swift. Coming from other languages, some of Swift’s concepts may seem unfamiliar, but spend some time working with them and you’ll quickly be able to master them.

See you in part three.