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
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. firstandlastare optionals, nil for an empty array, which makes them safe.- Reading
colours[5]when there are only 3 items crashes the app, so check withindices.contains(5)or loop over the array directly. isEmptyis clearer thancount == 0.
Changing a var array
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 itemsNone 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
| Method | Returns |
|---|---|
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
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:
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:
| Method | Answers |
|---|---|
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.
A to-do list
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"))["Buy milk", "Call Grandma", "Walk the dog", "Finish homework"]
1. Buy oat milk
2. Call Grandma
3. Finish homework
Homework on the list? trueLine-by-line explanation
- Line 2insert puts the item at position 1 and shifts the rest along.
- Line 3Arrays of strings print with quotes and square brackets.
- Line 5removeAll with a condition removes every matching item; $0 is each item.
- Line 6Replace the first item.
Scores: sorting, min, max and slices
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)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
-1Line-by-line explanation
- Line 2max and min return optionals, so ?? supplies a value for an empty array.
- Line 4sorted(by: >) returns a new array, highest first.
- Line 7The original order is unchanged.
- Line 12Checking indices first avoids a crash for a position that doesn't exist.
Arrays are copied
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)["Mon", "Tue", "Wed", "Thu", "Fri"]
["Mon", "Tue", "Wed", "Sat"]
9Line-by-line explanation
- Line 2plan gets its own copy of the array.
- Lines 3 to 4Changing plan doesn't affect weekdays.
- Line 85 plus 4 items.
Common Swift Arrays Mistakes
Changing a let array
let names = ["Ana"]
names.append("Ben") // error: cannot use mutating member on immutable valuevar names = ["Ana"]
names.append("Ben")Index out of range
let xs = [1, 2, 3]
print(xs[3]) // crash: Index out of rangeprint(xs.last ?? 0) // 3Mixing types in one array
let mixed = [1, "two", 3.0] // error: heterogeneous collection literal could only be inferred to '[Any]'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.
Complete the code so "eggs" is added to the end of the basket.
var basket = ["bread"]
basket.("eggs")
What does this print?
let xs = ["a", "b", "c", "d"]
print(xs[2])
What does this print?
var xs = [5, 3, 8]
xs.insert(1, at: 0)
xs.remove(at: 2)
print(xs)
What's the difference between sort() and sorted()?
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.
What is the type of
["red", "green"]?- String
- Array
- [Any]
- [String]
What does
[Int]().firstreturn?- 0
- nil
- A crash
- []
What does
xs.firstIndex(of: 7)return if 7 isn't present?- nil
- -1
- 0
- A crash
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
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