Introduction
Replacing an element at a specific index in a Swift array is done with subscript assignment: array[index] = newValue. Swift arrays are value types and are zero-indexed, so array[0] is the first element. You can also replace ranges of elements, use replaceSubrange, or swap elements. This article covers all the common array modification patterns in Swift with practical examples.
Basic Replacement by Index
1var fruits = ["Apple", "Banana", "Cherry", "Date"]
2
3// Replace element at index 1
4fruits[1] = "Blueberry"
5print(fruits) // ["Apple", "Blueberry", "Cherry", "Date"]
6
7// Replace the first element
8fruits[0] = "Avocado"
9print(fruits) // ["Avocado", "Blueberry", "Cherry", "Date"]
10
11// Replace the last element
12fruits[fruits.count - 1] = "Elderberry"
13print(fruits) // ["Avocado", "Blueberry", "Cherry", "Elderberry"]
The array must be declared with var (not let) to allow modification.
Safe Index Access
1var items = ["A", "B", "C"]
2
3// CRASH: index out of range
4// items[5] = "X" // Fatal error: Index out of range
5
6// Safe replacement with bounds checking
7func safeReplace(_ array: inout [String], at index: Int, with value: String) {
8 guard index >= 0, index < array.count else {
9 print("Index \(index) out of bounds (0..<\(array.count))")
10 return
11 }
12 array[index] = value
13}
14
15safeReplace(&items, at: 1, with: "Z")
16print(items) // ["A", "Z", "C"]
17
18safeReplace(&items, at: 10, with: "X")
19// Prints: Index 10 out of bounds (0..<3)
Array Extension for Safe Subscript
1extension Array {
2 subscript(safe index: Int) -> Element? {
3 get {
4 return indices.contains(index) ? self[index] : nil
5 }
6 set {
7 guard let newValue = newValue, indices.contains(index) else { return }
8 self[index] = newValue
9 }
10 }
11}
12
13var names = ["Alice", "Bob", "Charlie"]
14
15// Safe read
16print(names[safe: 1]) // Optional("Bob")
17print(names[safe: 5]) // nil
18
19// Safe write
20names[safe: 1] = "Barbara"
21print(names) // ["Alice", "Barbara", "Charlie"]
22
23names[safe: 10] = "Nobody" // No crash, silently ignored
Replacing a Range
1var colors = ["Red", "Green", "Blue", "Yellow", "Purple"]
2
3// Replace indices 1 through 3 with new elements
4colors[1...3] = ["Cyan", "Magenta"]
5print(colors) // ["Red", "Cyan", "Magenta", "Purple"]
6
7// The replacement can have a different count than the range
8colors[0..<2] = ["Black", "White", "Gray"]
9print(colors) // ["Black", "White", "Gray", "Magenta", "Purple"]
Range replacement uses ArraySlice assignment. The replacement array can be shorter or longer than the range.
Using replaceSubrange
1var letters = ["A", "B", "C", "D", "E"]
2
3// Replace range with new elements
4letters.replaceSubrange(1...3, with: ["X", "Y"])
5print(letters) // ["A", "X", "Y", "E"]
6
7// Insert elements (replace empty range)
8letters.replaceSubrange(2..<2, with: ["Z1", "Z2"])
9print(letters) // ["A", "X", "Z1", "Z2", "Y", "E"]
10
11// Remove elements (replace with empty array)
12letters.replaceSubrange(2...3, with: [])
13print(letters) // ["A", "X", "Y", "E"]
Swapping Elements
1var arr = ["First", "Second", "Third", "Fourth"]
2
3// Swap two elements
4arr.swapAt(0, 3)
5print(arr) // ["Fourth", "Second", "Third", "First"]
6
7// Reverse the entire array
8arr.reverse()
9print(arr) // ["First", "Third", "Second", "Fourth"]
Conditional Replacement
1var scores = ["Pass", "Fail", "Pass", "Fail", "Pass"]
2
3// Replace all "Fail" with "Retry"
4for i in scores.indices where scores[i] == "Fail" {
5 scores[i] = "Retry"
6}
7print(scores) // ["Pass", "Retry", "Pass", "Retry", "Pass"]
8
9// Using map for a new array (non-mutating)
10let updated = scores.map { $0 == "Retry" ? "Pending" : $0 }
11print(updated) // ["Pass", "Pending", "Pass", "Pending", "Pass"]
Finding and Replacing
1var cities = ["London", "Paris", "Berlin", "Paris", "Tokyo"]
2
3// Replace first occurrence
4if let index = cities.firstIndex(of: "Paris") {
5 cities[index] = "Lyon"
6}
7print(cities) // ["London", "Lyon", "Berlin", "Paris", "Tokyo"]
8
9// Replace all occurrences
10while let index = cities.firstIndex(of: "Paris") {
11 cities[index] = "Marseille"
12}
13print(cities) // ["London", "Lyon", "Berlin", "Marseille", "Tokyo"]
Common Pitfalls
Accessing an out-of-bounds index: array[index] = value crashes with "Fatal error: Index out of range" if index >= array.count or index < 0. Always verify the index is within 0..<array.count before assignment.
Trying to modify a let array: Arrays declared with let are immutable. let arr = ["A"]; arr[0] = "B" produces a compile error. Use var for arrays that need modification.
Confusing firstIndex(of:) with index(of:): In modern Swift, firstIndex(of:) is the correct method. The older index(of:) was renamed. Both return Optional<Int> — always unwrap before using as a subscript.
Mutating during for-in iteration: for item in array { array.remove(...) } causes undefined behavior or crashes. Use indices with where clause, iterate in reverse, or build a new array with filter/map.
Not handling the case where the element is not found: firstIndex(of:) returns nil if the element does not exist. Force-unwrapping the result (array[cities.firstIndex(of: "Missing")!]) crashes. Always use if let or guard let.
Summary
Replace by index with array[index] = newValue — the most common pattern
Always check bounds before subscript access to avoid crashes
Use array[range] = newElements or replaceSubrange for bulk replacements
Use swapAt(i, j) to swap two elements efficiently
Use firstIndex(of:) to find an element before replacing it
Use map for non-mutating transformations that produce a new array