Swift foreach() Function: A Complete Guide

In Swift, the forEach function is used to perform an operation for each element in an array.

For example, let’s print out an array of names using the forEach function:

let names = ["Alice", "Bob", "Charlie"]

names.forEach {
    print($0)
}

Output:

Alice
Bob
Charlie

In this guide, you learn how to use the forEach function to iterate over collections and ranges in Swift.

ForEach Function in Swift

In Swift, there are two main types of loops:

In addition to these, there is a functional way to iterate over a collection using the built-in forEach function.

Under the hood, forEach works similar to how a regular for loop works. The forEach function iterates over a collection and repeats an action for each element in the collection.

The official syntax of the forEach function looks like this:

func forEach(_ body: (Element) throws -> Void) rethrows

Where:

  • body is a closure function that takes each element in the sequence as its parameter at a turn.

The syntax of the forEach function probably looks verbose to you. No worries, usually the forEach function call looks something simple like this:

collection.forEach { element in
    operate(element)
}

Where operate means we perform an action for each element in the collection.

Commonly you can use an even tidier approach by using the $0.

collection.forEach { operate($0) }

Here $0 refers to each element in the collection at a turn.

For example, you can loop through an array of numbers and print each number out using the forEach function:

let nums = [1, 2, 3]

nums.forEach { number in
    print(number)
}

Output:

1
2
3

Or to make it a bit shorter:

let nums = [1, 2, 3]

nums.forEach {
    print($0)
}

Output:

1
2
3

The block of code inside the forEach function can be used to run any valid Swift code. However, it is important to notice the differences between forEach and for loop:

  1. You cannot use a break or continue statements in the forEach function closure to alter the flow of the loop.
  2. You cannot stop forEach function using the return statement.

Also, similar to for loops, any variable you create inside a forEach function closure is inaccessible outside of it.

[1, 2, 3].forEach {
    var something = 5000
    print($0)
}

print(something)

This results in an error:

main.swift:10:7: error: use of unresolved identifier 'something'
print(something)

The Swift compiler has no idea what something refers to. This happens because something is declared inside the scope of the forEach function’s closure. Anything accessible inside this closure cannot be accessed outside of its scope.

However, you can indeed access objects declared outside of the scope of the closure inside of it.

For instance:

var x = 1000

[1, 2, 3].forEach {
    print($0)
    x += 100
}

print(x)

Output:

1
2
3
1300

Now that you understand how the forEach function works in Swift, let’s start using it.

ForEach with Collections in Swift

Next up, you are going to learn how to use the forEach function to perform an action for each element with:

Loop Through Arrays with forEach

In Swift, an array is a popular data type. You can use an array to store objects for easy access.

For example, you can store a group of names in an array. Later, you can perform some actions for each name in the array, such as filtering them based on if they contain invalid characters.

To loop through each element in an array, you can use the forEach function.

For instance, let’s loop through an array of strings and print each name out:

let names = ["Alice", "Bob", "Charlie"]

names.forEach {
    print($0)
}

Output:

Alice
Bob
Charlie

Loop Through Key-Value Pairs in a Dictionary Using forEach

A dictionary is also a very commonly used data type in Swift.

Unlike an array, you can store key-value pairs in a dictionary. A dictionary thus associates each key with a value. You can later use that key to access the corresponding value.

To perform an action for each element in a dictionary, you can use the built-in forEach function.

As you operate on a dictionary, you should store the key and the value to different variables. What is cool is that the forEach function does this for you. It assigns the key to $0 and the value to $1 automatically.

For example, let’s loop through a dictionary using the forEach function and print each key-value pair:

let data = [
    "name": "Alice",
    "age": "30",
    "address": "Imaginary Road 22"
]

data.forEach {
    print("\($0): \($1)")
}

Output:

address: Imaginary Road 22
name: Alice
age: 30

If this confuses you, write the closure explicitly by specifying the key and value parameters like this:

let data = [
    "name": "Alice",
    "age": "30",
    "address": "Imaginary Road 22"
]

data.forEach { key, value in 
    print("\(key): \(value)")
}

Output:

address: Imaginary Road 22
name: Alice
age: 30

Loop Through the Letters in a String Using forEach

In Swift, a String is a collection of characters. This means you can call the forEach function on a string. This looks identical to how you would call forEach on an array of objects.

For example, let’s print each character in a string:

let greeting = "Hello"

greeting.forEach {
    print($0)
}

Output:

H
e
l
l
o

Loop Through the Enum Cases Using forEach

In Swift, an enumeration groups together related values in a type-safe way.

What you might not know is you can loop through the enumeration cases quite easily. To do that you need to make enumeration CaseIterable. After this, you can access the enumeration cases via allCases. This returns an array of the enumeration cases. You can then use forEach to loop through this collection.

For instance, let’s print the cases of an enumeration:

enum Direction: CaseIterable {
    case North
    case East
    case South
    case West
}

Direction.allCases.forEach {
    print($0)
}

Output:

North
East
South
West

So far you have seen examples of how to use the forEach function to loop through collections in Swift.

Next, let’s use the forEach function on ranges in Swift.

ForEach with Ranges in Swift

A range is an interval from the lower bound to the upper bound.

Swift has two different range types:

You can use the forEach function to loop through these ranges in Swift.

Closed Range

In Swift, you can create a closed range of values using the operator.

start...end

Where:

  • start is the value at which the range starts.
  • end is the value at which the range ends. This is included in the range.

A result is a range object that goes from start to end with one-step intervals.

Similar to looping through collections in Swift, you can loop through a range using the forEach function.

For example:

(1...5).forEach {
    print($0)
}

Output:

1
2
3
4
5

Half-Open Range

There is another type of range in Swift. It is called the half-open range. To create one, use the ..< operator.

start..<end

Where

  • start is the number at which the range starts.
  • end is the end number for the range. In a half-open range it is not included in the range.

You can also use the forEach function to loop through a half-open range.

For example, let’s print numbers from 1 to 4:

(1..<5).forEach {
    print($0)
}

Output:

1
2
3
4

ForEach with Stride in Swift

To create a range with a step size other than 1, you need to use a stride.

A stride can be created with the following syntax:

stride(from:to:by)

Where:

  • from is the starting number.
  • to is the (excluded) end number.
  • by is the stepsize. With a negative value it reverses the order.

A stride object can also be looped through with the forEach function.

For example:

for n in stride(from: 10, to: 0, by: -2) {
    print(n)
}

Output:

10
8
6
4
2

ForEach with Index in Swift

Sometimes you may want to keep track of the index when looping through a collection.

By default, the forEach function has no idea about the index of the current element. To change this, you can specify a separate variable that you update on each iteration of the loop.

However, this is not elegant.

Tracking the index of a collection is so common that Swift has a built-in mechanism for it. To associate each element in an array with an index, use the Array.enumerated() function. This returns an array of index-item pairs you can iterate over.

For example, let’s create an array of names that represents a queue. Then, let’s print the names in the queue and their position:

let names = ["Alice", "Bob", "Charlie"]

print("Queue order:")
names.enumerated().forEach {
    print(" \($0 + 1). \($1)")
}

Output:

Queue order:
 1. Alice
 2. Bob
 3. Charlie

If you find this piece of code confusing, you can explicitly declare the parameters into the forEach closure:

let names = ["Alice", "Bob", "Charlie"]

print("Queue order:")
names.enumerated().forEach { position, name in 
    print(" \(position + 1). \(name)")
}

Output:

Queue order:
 1. Alice
 2. Bob
 3. Charlie

If you only need the indices, use the Array.indices property. This returns a collection of indices that represent each element in the original array.

For instance:

let names = ["Alice", "Bob", "Charlie"]

names.indices.forEach {
    print($0)
}

Output:

0
1
2

Next, let’s take a look at how to deal with optionals in for loops.

ForEach with Optionals in Swift

Sometimes a collection consists of optional, that is, objects that can be either defined or nil.

When using a regular for loop, you can use the for case let approach to leave nil values out. However, this is not possible using the forEach function. Instead, you have to check if an element is nil or not separately inside the closure.

For example, let’s handle optional strings so that we do not print the nils:

let names: [String?] = ["Alice", nil, nil, "Bob", "Charlie", nil]

names.forEach { name in
    if let name = name {
        print(name)
    }
}

Output:

Alice
Bob
Charlie

When Use forEach Instead of For Loop in Swift

For the most part, using forEach and a for loop is interchangeable.

The main difference between the forEach function and a regular for loop is that:

  1. You cannot use break or continue statements in the forEach function.
  2. Using return does not stop the forEach function.

In other words, you cannot control the flow of the forEach function the same way you can control a for loop. This is the only real difference.

If you want to be able to control the flow of a loop, then you should not use forEach.

Notice that using the forEach function represents the functional programming paradigm. If you are using for loops elsewhere in the codebase, then stick with them to be consistent. But if the codebase has functional code, then feel free to use forEach.

In functional programming, forEach is neater than a regular for loop. This is because you can chain a forEach call with other higher-order function calls.

For instance, let’s take the square root of an array of floating-point values such that we:

  • Filter out the negative values using the filter function.
  • Take the square root of each element using the map function.
  • Print each element using the forEach function.
import Foundation

let numbers = [-10.0, 5.9, 7.2, 3.1, -24.5, 4.05, -90.12, -1.2, 5.8]

let result = numbers.filter { $0 >= 0 }
                    .map { sqrt($0) }
                    .forEach { print($0) }

Output:

2.4289915602982237
2.6832815729997477
1.760681686165901
2.0124611797498106
2.4083189157584592

The forEach call is chained with the other function calls. If you used a regular for loop instead, the code complexity would increase a bit:

import Foundation

let numbers = [-10.0, 5.9, 7.2, 3.1, -24.5, 4.05, -90.12, -1.2, 5.8]

let result = numbers.filter { $0 >= 0 }
                    .map { sqrt($0) }

for number in result {
    print(number)
}

Conclusion

Today you learned how to use the forEach function to loop through collections and ranges in Swift.

To recap, you can replace a regular for loop with a functional forEach approach.

The only difference between a regular for loop and the forEach function is you cannot control the flow of forEach. In other words, continue and break statements cannot be used. Also, the return statement does not halt the process.

You can use forEach in the functional programming approach to make chains of higher-order functions without having to write lengthy for loops.

Scroll to Top