An array in Swift can contain any type of data, values types as well as reference types. The type of data an array stores can sometimes be quite complex, though. In this episode, I show you how to store dictionaries in an array and I show you why an array of dictionaries is usually not what you need or even want.

Storing Elements in an Array

Fire up Xcode and create a playground by choosing the Blank template from the iOS > Playground section.

Working with Arrays of Dictionaries in Swift

There are several ways to create an array in Swift. An array literal is the most straightforward option. Take a look at this example.

import Foundation

let integers = [1, 2, 3, 4]

The compiler can infer the type of the array by inspecting the elements of the array literal. This is known as type inference.

We can't take advantage of type inference if we want to create an empty array of integers. We explicitly specify the type of the array to make it clear the array is of type [Int], an array of integers.

import Foundation

let integers: [Int] = []

Creating an Array of Dictionaries

An array of dictionaries is no different. The array literal is a bit more complex, but that is the only difference. In this example, we create an array of dictionaries using an array literal.

import Foundation

let users = [
    [
        "first": "Lucy",
        "last": "Johnson"
    ],
    [
        "first": "John",
        "last": "Williams"
    ]
]

We don't need to specify the type of the array thanks to type inference. As I mentioned earlier, we can't rely on type inference if the array is empty. The syntax may look confusing, but it is pretty straightforward. We assign an empty array, an array of dictionaries, to users.

import Foundation

let users: [[String:String]] = []

The type of the array is [[String:String]]. The elements the array holds are of type [String:String]. We can simplify this by defining a type alias for the elements of the array. Take a look at the updated example.

import Foundation

typealias User = [String:String]
let users: [User] = []

As the name suggests, a type alias is nothing more than a named alias for a type. Notice how the declaration of users becomes much easier to read and understand.

Structs and Dictionaries

I rarely use arrays of dictionaries in Swift. It is easier and more convenient to create a struct that encapsulates the data the dictionary stores. Take a look at the updated example below.

import Foundation

struct User {
    
    let first: String
    let last: String
    
}

let users: [User] = [
    User(first: "Lucy", last: "Johnson"),
    User(first: "John", last: "Williams")
]

It is true that we added a few additional lines of code to implement the User struct, but the benefits far outweigh those handful of lines of code. The declaration of users is easier to read and we don't need a type alias. The array literal we assign to users is easier on the eyes and, more importantly, the compiler makes sure we don't make typos.

Bugs and Stringly Typed Code

Dictionaries are useful, but it is important to know when (not) to use them. When strings, and very often string literals, are used instead of a more appropriate type, we speak of stringly typed code. Some forms of stringly typing are obvious while others are more subtle. The next example illustrates the danger of dictionaries and stringly typed code.

import Foundation

let users = [
    [
        "first": "Lucy",
        "last": "Johnson"
    ],
    [
        "first": "John",
        "last": "Williams"
    ]
]

print(users.first?["firstt"])

We ask the array of users for the first element and access the value for key firstt. The result is nil, because we misspelled the key (firstt instead of first).

We can't make this mistake if we replace the array of dictionaries with an array of User objects. The compiler immediately notifies us that we made a typo.

import Foundation

struct User {
    
    let first: String
    let last: String
    
}

let users: [User] = [
    User(first: "Lucy", last: "Johnson"),
    User(first: "John", last: "Williams")
]

print(users.first?.firstt)

Working with Arrays of Dictionaries in Swift

What's Next?

The key takeaways for this episode are simple but powerful. First, use dictionaries when it is appropriate to use them. Second, use a type alias to keep your code readable and easier to understand.