Swift Arrays

Store ordered lists of values in arrays, read and change items safely, add and remove items, and use built-in methods to search, sort and slice.

Lesson 9 of 43Beginner18 min read

Most data in apps comes in lists: the messages in a conversation, the songs in a playlist, the items in a basket, the scores in a game. Swift stores ordered lists in arrays.

An array holds values of a single type, written [String] or [Int], in a fixed order, and you read items by their position, starting from 0. Arrays declared with let can't change; arrays declared with var can grow, shrink and be rearranged.

Swift arrays are value types: assigning an array to another variable makes an independent copy, so changing one never affects the other. That's different from many languages and removes a whole category of bugs. In this lesson you'll create arrays, read and change items, add and remove them, and use the built-in methods for searching, sorting and slicing.

Creating and reading arrays

Swift
let colours = ["red", "green", "blue"]       // [String]
var scores: [Int] = []                        // empty, type given
print(colours[0])          // red
print(colours.count)       // 3
print(colours.first ?? "") // red
  • Indexes start at 0, so the last item is at count - 1.
  • first and last are optionals, nil for an empty array, which makes them safe.
  • Reading colours[5] when there are only 3 items crashes the app, so check with indices.contains(5) or loop over the array directly.
  • isEmpty is clearer than count == 0.

Changing a var array

Swift
var basket = ["apples", "bread"]
basket.append("milk")                // at the end
basket.insert("eggs", at: 0)         // at a position
basket[1] = "green apples"           // replace
basket.remove(at: 2)                 // by position, returns the item
basket += ["tea", "jam"]             // add several
basket.removeAll { $0 == "tea" }     // remove matching items

None of these work on a let array; the compiler will tell you to make it a var. removeLast() and removeFirst() remove from the ends, but crash on an empty array, so check isEmpty first or use popLast(), which returns an optional.

Searching, sorting and slicing

MethodReturns
contains(x)true if the item is present
firstIndex(of: x)its position, or nil
sorted() / sorted(by: >)a new sorted array
sort()sorts a var array in place
reversed()the items in reverse order
prefix(3) / suffix(3)the first or last three items
array[1...3]an ArraySlice of positions 1 to 3
min(), max()optionals, nil when empty

Slices share storage with the original array; wrap them in Array(...) to store them on their own.

Value semantics

Swift
var original = [1, 2, 3]
var copy = original
copy.append(4)
print(original)   // [1, 2, 3]
print(copy)       // [1, 2, 3, 4]

Assigning or passing an array gives the receiver its own array. Behind the scenes Swift only actually copies the data when one side changes ("copy on write"), so this safety costs very little.

Repeated values and arrays of arrays

Array(repeating:count:) builds an array with the same value several times, which is handy for starting scores or an empty board:

Swift
var lives = Array(repeating: 3, count: 4)    // [3, 3, 3, 3]
var grid = Array(repeating: Array(repeating: 0, count: 3), count: 2)
grid[1][2] = 5
print(grid)                                  // [[0, 0, 0], [0, 0, 5]]

An array can hold other arrays, giving you rows and columns. The type is written [[Int]], and grid[1][2] means row 1, column 2. Because arrays are values, each row is independent, so changing one row never affects another.

Searching with a condition

contains(x) and firstIndex(of: x) look for an exact value. When you're searching by a rule instead, use the versions that take a closure. Inside it, $0 stands for each item in turn:

MethodAnswers
contains { $0 > 10 }Does any item match?
allSatisfy { $0 > 0 }Does every item match?
first { $0 > 5 }The first matching item, or nil
firstIndex { $0 > 5 }Where the first match is, or nil

With [3, 8, 12, 5], these give true, true, 8 and 1. They stop as soon as they know the answer, so they're also quicker than writing the loop yourself. The closures lesson explains the { $0 > 10 } syntax fully.

Swift Arrays Syntax

Array essentials

var xs = [3, 1, 2]
let empty: [String] = []
xs[0]   xs.count   xs.isEmpty   xs.first   xs.last
xs.append(4)   xs.insert(0, at: 0)   xs.remove(at: 1)
xs.removeAll { $0 > 2 }
xs.contains(3)   xs.firstIndex(of: 3)
xs.sorted()   xs.sorted(by: >)   xs.sort()   xs.reversed()
xs.prefix(2)   Array(xs[1...2])

Swift Arrays Summary

  • Arrays hold ordered values of one type: [String], [Int]. Indexes start at 0.
  • first, last, min and max are optionals; out-of-range indexes crash.
  • var arrays support append, insert, remove(at:), removeAll(where:) and +=.
  • contains, firstIndex(of:), sorted, reversed, prefix and slices help search and reshape.
  • Arrays are value types: copies are independent.

Swift Arrays Examples

Each example shows the code, the output it produces and what each part does.

Example 1

A to-do list

Swift
var todo = ["Buy milk", "Walk the dog", "Finish homework"]
todo.insert("Call Grandma", at: 1)
print(todo)

todo.removeAll { $0 == "Walk the dog" }
todo[0] = "Buy oat milk"

for (i, task) in todo.enumerated() {
    print("\(i + 1). \(task)")
}
print("Homework on the list?", todo.contains("Finish homework"))
Output
["Buy milk", "Call Grandma", "Walk the dog", "Finish homework"]
1. Buy oat milk
2. Call Grandma
3. Finish homework
Homework on the list? true
Line-by-line explanation
  1. Line 2insert puts the item at position 1 and shifts the rest along.
  2. Line 3Arrays of strings print with quotes and square brackets.
  3. Line 5removeAll with a condition removes every matching item; $0 is each item.
  4. Line 6Replace the first item.
Example 2

Scores: sorting, min, max and slices

Swift
let scores = [72, 95, 58, 88, 64]
print("Highest:", scores.max() ?? 0, "Lowest:", scores.min() ?? 0)

let ranked = scores.sorted(by: >)
print("Ranked:", ranked)
print("Top 3:", Array(ranked.prefix(3)))
print("Original:", scores)

if let position = scores.firstIndex(of: 88) {
    print("88 is at index \(position)")
}
print(scores.indices.contains(10) ? scores[10] : -1)
Output
Highest: 95 Lowest: 58
Ranked: [95, 88, 72, 64, 58]
Top 3: [95, 88, 72]
Original: [72, 95, 58, 88, 64]
88 is at index 3
-1
Line-by-line explanation
  1. Line 2max and min return optionals, so ?? supplies a value for an empty array.
  2. Line 4sorted(by: >) returns a new array, highest first.
  3. Line 7The original order is unchanged.
  4. Line 12Checking indices first avoids a crash for a position that doesn't exist.
Example 3

Arrays are copied

Swift
var weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri"]
var plan = weekdays
plan.removeLast(2)
plan.append("Sat")

print(weekdays)
print(plan)
print(weekdays.count + plan.count)
Output
["Mon", "Tue", "Wed", "Thu", "Fri"]
["Mon", "Tue", "Wed", "Sat"]
9
Line-by-line explanation
  1. Line 2plan gets its own copy of the array.
  2. Lines 3 to 4Changing plan doesn't affect weekdays.
  3. Line 85 plus 4 items.

Common Swift Arrays Mistakes

Changing a let array

Don't
let names = ["Ana"]
names.append("Ben")          // error: cannot use mutating member on immutable value
Do
var names = ["Ana"]
names.append("Ben")

Index out of range

Don't
let xs = [1, 2, 3]
print(xs[3])                 // crash: Index out of range
Do
print(xs.last ?? 0)          // 3

Mixing types in one array

Don't
let mixed = [1, "two", 3.0]  // error: heterogeneous collection literal could only be inferred to '[Any]'
Do
let numbers = [1, 2, 3]
let words = ["one", "two"]

Use a struct when related values of different types belong together.

Swift Arrays in Real Projects

Arrays in apps

SwiftUI lists and grids are built from arrays: List(messages) { ... } shows one row per item. Apps keep their data as arrays of structs, sort and filter them for display, and replace the array when something changes so the screen updates. Arrays being value types makes this safe, because a screen can't be changed by code that only received a copy.

Swift Arrays FAQ

How do I check if an array is empty in Swift?

Use array.isEmpty, which reads clearly and is always fast. array.count == 0 gives the same answer but is less idiomatic. To read the first item safely at the same time, use if let first = array.first.

Why does my Swift app crash with "Index out of range"?

You read or wrote a position that doesn't exist, such as items[3] when there are only three items at 0, 1 and 2. Loop over the items directly, use first and last, or check items.indices.contains(i) before using a calculated index.

What is the difference between sort() and sorted() in Swift?

sort() reorders a var array in place and returns nothing. sorted() leaves the original untouched and returns a new sorted array, so it also works on let arrays. The same -ed naming pattern appears in reverse() and reversed().

How do I remove duplicates from an array in Swift?

Array(Set(items)) removes duplicates, but loses the original order. To keep the first occurrence of each item in order, loop through the array and append items you haven't seen before, tracking them in a Set.

Are Swift arrays passed by value or by reference?

By value. Assigning an array or passing it to a function gives the receiver its own copy, so changes on one side don't affect the other. Swift delays the actual copy until one side changes, which keeps this cheap.

Swift Arrays Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the code so "eggs" is added to the end of the basket.

var basket = ["bread"]
basket.("eggs")
Predict the outputeasy

What does this print?

let xs = ["a", "b", "c", "d"]
print(xs[2])
Predict the outputmedium

What does this print?

var xs = [5, 3, 8]
xs.insert(1, at: 0)
xs.remove(at: 2)
print(xs)
Multiple choicemedium

What's the difference between sort() and sorted()?

Predict the outputhard

What does this print?

var a = [1, 2]
var b = a
b.append(3)
print(a.count, b.count)

Swift Arrays Quiz

5 questions to check what you learned.

  1. What is the type of ["red", "green"]?

    • String
    • Array
    • [Any]
    • [String]
  2. What does [Int]().first return?

    • 0
    • nil
    • A crash
    • []
  3. What does xs.firstIndex(of: 7) return if 7 isn't present?

    • nil
    • -1
    • 0
    • A crash
  4. What does removeAll { $0 < 0 } do?

    • Removes the first negative number
    • Empties the array
    • Removes every item that's less than zero
    • Returns a new array
  5. Why does assigning an array to another variable not link them?

    • It's a bug
    • Arrays are value types: each variable gets its own copy (copied lazily on write)
    • Arrays are classes
    • Only let arrays are copied