In the previous article, you learned about variables, constants, and some of the common data types, such as integers, floats, and strings. In this article, we zoom in on collections. Swift's standard library defines two collection types, arrays and dictionaries. Let's start with arrays.
The first important difference with arrays in Objective-C is that the values stored in an array are always of the same type. At first, this may seem like a significant limitation, but it actually isn't. In fact, this limitation has an important advantage. We know exactly what type we get back when we ask the array for one of its values.
Another key difference with Objective-C arrays is the type of values an array can store. In Objective-C, an array can only store values of a class type. Swift doesn't have this limitation. An array in Swift can store strings, integers, floats as well as class instances. How this works and why this is possible in Swift will become clear later in this series when we cover classes and structures.
While creating an array can be done several ways, you need to keep in mind that Swift needs to know what type of values you plan to store in the array. Create a new playground in Xcode like we did in the previous article and add the following lines to your playground.
var array1: Array<String> var array2: [String] var array3 = ["Apple", "Pear", "Orange"]
The second line is shorthand for the first line. The square brackets wrapping the
String keyword tell Swift that we're declaring an array that can only contain
You could read the first line of code as "We declare a variable named
array1 of type
Array that can only contain
String objects." Note that I italicized of type since that is what the colon signifies.
The third line shows us how to initialize an array using an array literal. Array literals look very similar to array literals in Objective-C. The main difference is the absence of the
@ symbol preceding the square brackets and the string literals.
There's also a fancy way to initialize an array with a predefined number of default values. The syntax may be confusing at first, but take a moment to let it sink in.
var a = [String](count: 5, repeatedValue: "Test")
The resulting array contains five strings, with each string being equal to
"Test". To better understand the above initialization, take a look at the following two lines of code in which we initialize an empty array of strings.
var b = Array<String>() var c = [String]()
Don't worry if you're still confused. We'll explore the syntax in more detail once we start dealing with classes and functions. In this article, we're only focusing on collections.
One aspect of Swift that you'll quickly come to appreciate is how to declare mutable collections. The above code snippet, for example, declares three mutable arrays. A mutable array is defined by using the
var keyword. It's that simple. If you don't want an array to be mutable, then use the
let keyword instead. Swift aims to be intuitive and easy to use, and Swift's implementation of mutability is a perfect example of this goal.
Getting and Setting Values
To access the values stored in an array, we use the same subscript syntax as in Objective-C. In the following example, we ask
array3 for its second element, the string
Replacing the value stored at index
1 is as simple as assigning a new value using the same subscript syntax. In the following example, we replace
"pear" at index
array3 = "Peach"
This is only possible because the array is mutable, that is, we used the
var keyword to declare the array. Mutating a constant array isn't possible. There are more advanced techniques for manipulating the contents of an array, but the underlying concept is the same.
Merging two arrays is as simple as adding them together. In the following example, we declare and merge two immutable arrays. Note that the resulting array,
c, doesn't need to be mutable for this to work.
let a = [1, 2, 3] let b = [4, 5, 6] let c = a + b
However, it is key that the values stored in
b are of the same type. The reason should be obvious by now. The values stored in an array need to be of the same type. The following example will result in an error.
let a = [1, 2, 3] let b = [1.5, 5.2, 6.3] let c = a + b
To append an array to a mutable array, we use the
+= operator. Note that the operand on the right is an array. This operation wouldn't work if we removed the square brackets surrounding
var a = [1, 2, 3] a += 
Arrays are objects on which you can perform a wide range of operations. Arrays expose a number of functions or methods. To invoke a method on an object, you use the dot notation. Add the following line to your playground to add an item to
Let's see how many items
array3 contains by invoking its
count method. This outputs
4 in the results pane on the right.
It's also possible to insert an item at a specific index by invoking the array's
insert method as shown below. The
insert method accepts more than one parameter and it may look a bit odd at first.
array3.insert("Prune", atIndex: 2)
Like Objective-C, Swift supports named parameters to improve readability. The result is that code is easier to read and understand, and functions or methods don't need much explaining in terms of what they do. It is clear, for example, that the
insert method inserts an element at index
What I really enjoy about Swift are the Ruby-like convenience properties and methods of Swift's standard library. An array, for example, has an
isEmpty property that tells you if the array contains any elements. This is nothing more than shorthand for checking the array's
count property. The result, however, is code that is more concise and easier to read.
Dictionaries behave very similar to dictionaries in Objective-C. A dictionary stores an unordered collection of values. Each value in the dictionary is associated with a key. In other words, a dictionary stores a number of key/value pairs.
As with arrays, the keys and values stored in a dictionary need to be of the same type. This means that if you ask a dictionary for the value of a particular key, you know what type the dictionary will return.
Declaring a dictionary is similar to declaring an array. The difference is that you need to specify the type for both keys and values. The following example shows three ways to declare a dictionary.
var dictionary1: Dictionary<String, Int> var dictionary2: [String: Int] var dictionary3 = ["Apple": 3, "Pear": 8, "Orange": 11]
The second line is shorthand for the first line. The keys of these dictionaries need to be of type
String while the values are expected to be of type
var keyword indicates that the dictionaries are mutable.
You could read the first line of code as "We declare a variable named
dictionary1 of type
Dictionary that can only contain keys of type
String and values of type
The third line illustrates how we can initialize a dictionary using a dictionary literal. This is similar to the syntax we use in Objective-C, but note that the curly braces are replaced by square brackets and the literal isn't prefixed with an
Getting and Setting Values
Accessing values is similar to accessing values of an array. The only difference is that you use the key instead of the index of the value you need to access. The following example illustrates this.
let value = dictionary3["Apple"] println(value)
You'll notice that Xcode tells us that the value of
Optional(3). What does this mean? Swift uses optionals to wrap values that can be one of two things, a value or
nil. Don't worry about optionals at this point. We're going to focus on optionals in the next article of this series. Let me just tell you that optionals are another key concept of the Swift programming language.
It's interesting to point out that the syntax to access a value of a dictionary is identical to that of arrays if the keys of the dictionary are of type
Int. Take a look at the following example to see what I mean.
var dictionary4 = [0: "Apple", 1: "Pear", 2: "Orange"] let fruit = dictionary4
As with arrays, the Swift standard library defines a wide range of operations you can perform on dictionaries. A dictionary returns its number of key/value pairs by calling
count on it. Removing a key/value pair is easy and intuitive as the next example illustrates. Of course, this is only possible if the dictionary is mutable.
When you start learning Swift, you'll occasionally run into code snippets that look odd or confusing. Take a look at the following line in which we first declare a dictionary and then remove its key/value pairs.
var dictionary = [String: Int]() dictionary["Oranges"] = 2 dictionary["Apples"] = 10 dictionary["Pears"] = 5 dictionary = [:]
You have to admit that the last line looks a bit odd. Because Swift knows the types of the keys and values that can be stored in
dictionary, emptying the dictionary is as simple as assigning an empty dictionary to it.
There's no need to specify the types for the keys and values in this case, because we already did when we declare the dictionary in the first line. This points out another important detail, that is, the type of values you can store in arrays and dictionaries cannot change once the collection is declared.
You are going to love tuples. While tuples aren't collections, they also group multiple values. Similar to arrays and dictionaries, tuples can contain values of any type. The key difference, however, is that the values stored in a tuple don't need to be of the same type. Let's look at an example to explain this in more detail.
var currency = ("EUR", 0.81) var time = (NSDate(), "This is my message.") var email = ("Bart Jacobs", "email@example.com")
The first example declares a tuple named
currency that is of type
(String, Int). The second tuple, time, contains an
NSDate instance and a string literal. The values stored in
String, which means
To access a value stored in a tuple, you use the index that corresponds with the value you're interested in.
var rate = currency.1 var message = time.1 var name = email.0
Xcode shows us the indexes of each value stored in a tuple in the results pane of the playground on the right.
To improve readability, you can name the values stored in a tuple. The result is that you can access the values of the tuple through their names instead of their indexes. Declaring a tuple is slightly different in that case.
var currency = (name: "EUR", rate: 0.81) let currencyName = currency.name let currencyRate = currency.rate
There's a second, more elegant way to work with the values stored in a tuple. Take a look at the following example in which we decompose the contents of
let (currencyName, currencyRate) = currency
The value of
currency at index
0 is stored in
currencyName and the value at index
1 is stored in
currencyRate. There's no need to specify the type for
currencyRate since Swift infers the type from the values stored in
currency. In other words,
currencyName is of type
currencyRate is of type
If you're only interested in specific values of a tuple, you can use an underscore to tell Swift which values you're not interested in.
let (currencyName, _) = currency
Learn More in Our Swift Programming Course
Take your Swift education to the next level and learn about everything from Playgrounds through to Object Oriented Programming in our full course on Swift development.
Arrays and dictionaries are fundamental components of almost every programming language and Swift is no different. While collections behave a little differently in Swift, it doesn't take long to become familiar with Swift's collection types if you've worked with arrays and dictionaries in other programming languages. In the next tutorial, we explore optionals and control flow.