# Swift for-in Loops: Syntax, Examples, and Common Mistakes

Source: https://devdocs10.com/articles/swift/swift-for-in  
By Murat Bo · Published 2026-05-12 · DevDocs10 (https://devdocs10.com)

Swift `for-in` loops are the standard way to repeat work over a sequence of values such as ranges, arrays, dictionaries, sets, and strings. If you are learning Swift, understanding `for-in` loops will help you write clearer code, avoid manual index handling, and work naturally with the Swift standard library.

> **Quick answer:** A Swift `for-in` loop takes each value from a sequence one at a time and runs a block of code for it. You use it when you want to iterate over items safely and readably, instead of managing counters yourself.

> **Difficulty:** Beginner
>
> **Helpful to know first:** You'll understand this better if you know basic Swift syntax, how variables store values, and simple types like `String`, `Int`, and arrays.

## 1. What Is for-in in Swift?

A `for-in` loop repeats a block of code once for each element in a sequence or collection. In Swift, this is the normal way to iterate through values because it is expressive, safe, and works with many standard library types.

- It loops over each value in order when the type has a meaningful order, such as arrays and ranges.
- It works with ranges like `1...5` and `1..<5`.
- It works with collections such as arrays, dictionaries, sets, and strings.
- It avoids many index-related errors that beginners often make.
- It can include filtering logic using `where`.

Swift developers often compare `for-in` with `while`. A `for-in` loop is best when you already have a sequence of values to iterate over. A `while` loop is better when repetition depends on a changing condition instead of a collection or range.

## 2. Why for-in Matters

`for-in` loops matter because most real programs need to process multiple values: printing a list of names, summing numbers, validating input, transforming text, or reading key-value pairs. Swift is designed to encourage this style of iteration instead of low-level manual counting.

Use `for-in` when:

- You need to visit every item in an array or other collection.
- You want to repeat something a known number of times using a range.
- You want cleaner code than manually updating an index variable.
- You want safer iteration over strings and collections.

Do not use it when:

- You need a loop that continues until a condition changes unpredictably; `while` may fit better.
- You only need a one-off operation and no repetition is involved.
- You need special sequence operations where methods like `map`, `filter`, or `reduce` express the intent more clearly.

## 3. Basic Syntax

The core syntax is simple: declare a temporary loop value, use `in`, then provide the sequence you want to iterate over.

### Basic form

This example loops over a closed range from 1 through 3.

```swift
for number in 1...3 {
    print(number)
}
```

Output (tested with Swift 6.4):

```text
1
2
3
```

On each iteration, Swift assigns the next value in the range to `number`. The output is 1, then 2, then 3.

### Understanding the parts

In the loop above:

- `for` starts the loop.
- `number` is the temporary constant for the current item.
- `in` connects the loop variable to the sequence.
- `1...3` is the sequence being iterated.
- The braces contain the code that runs for each value.

### Ignoring the loop value

If you only want to repeat something and do not need the current value, use an underscore.

```swift
for _ in 1...3 {
    print("Hello")
}
```

Output (tested with Swift 6.4):

```text
Hello
Hello
Hello
```

This prints `Hello` three times. The underscore tells Swift that the individual values are intentionally unused.

## 4. Step-by-Step Examples

The best way to learn `for-in` is to see it used with different Swift types.

### Example 1: Looping through a range

Ranges are one of the most common things to use with `for-in`. This example prints countdown numbers.

```swift
for count in 1...5 {
    print("Count: \(count)")
}
```

Output (tested with Swift 6.4):

```text
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
```

This loop visits each number from 1 through 5. A closed range includes both endpoints.

### Example 2: Looping through an array

Arrays are ordered collections, so `for-in` visits each item in order.

```swift
let fruits = ["Apple", "Banana", "Cherry"]

for fruit in fruits {
    print("Fruit: \(fruit)")
}
```

Output (tested with Swift 6.4):

```text
Fruit: Apple
Fruit: Banana
Fruit: Cherry
```

Each loop cycle gives you one element from the array. This is usually better than manually accessing indexes unless you specifically need the index too.

### Example 3: Looping through a dictionary

Dictionaries store key-value pairs. In Swift, you can unpack both parts directly in the loop.

```swift
let scores = ["Ana": 95, "Ben": 88, "Cara": 91]

for (name, score) in scores {
    print("\(name): \(score)")
}
```

Output (tested with Swift 6.4):

```text
Ana: 95
Ben: 88
Cara: 91
```

This gives you each key and value as a pair. One important detail is that dictionary iteration order should not be relied on unless you explicitly sort the data first.

### Example 4: Looping through a string

Swift strings are collections of characters, so you can iterate through them directly.

```swift
let word = "Swift"

for character in word {
    print(character)
}
```

Output (tested with Swift 6.4):

```text
S
w
i
f
t
```

This prints one character per line. Swift handles characters safely, which is especially important for Unicode text.

### Example 5: Using where in a for-in loop

You can add a `where` clause to process only matching values.

```swift
for number in 1...10 where number % 2 == 0 {
    print("Even: \(number)")
}
```

Output (tested with Swift 6.4):

```text
Even: 2
Even: 4
Even: 6
Even: 8
Even: 10
```

This loop prints only the even numbers. The `where` clause is a clean way to filter values during iteration.

## 5. Practical Use Cases

- Displaying each item in a shopping list stored in an array.
- Summing scores, prices, or counts from a numeric collection.
- Checking each character in a password for validation rules.
- Processing dictionary entries such as usernames and account balances.
- Repeating an action a fixed number of times with a range.
- Filtering values inline with `where`, such as printing only active users or only even numbers.
- Generating text output like numbered menu items or progress messages.

## 6. Common Mistakes

### Mistake 1: Using the wrong range operator

Swift has both closed and half-open ranges, and beginners often choose the wrong one. That leads to loops running one time too many or one time too few.

**Problem:** This code uses a closed range when the goal is to repeat exactly three times starting at zero, so it runs four times instead of three.

```swift
for index in 0...3 {
    print(index)
}
```

Output (tested with Swift 6.4):

```text
0
1
2
3
```

**Fix:** Use a half-open range when the upper bound should not be included.

```swift
for index in 0..<3 {
    print(index)
}
```

Output (tested with Swift 6.4):

```text
0
1
2
```

The corrected version works because `0..<3` includes 0, 1, and 2 but not 3.

### Mistake 2: Expecting dictionary items in a fixed order

Many beginners assume dictionaries behave like arrays during iteration. In Swift, dictionary order should not be treated as a guaranteed sorted display order.

**Problem:** This code assumes names will always print in the same meaningful order, which can produce inconsistent results.

```swift
let scores = ["Ben": 88, "Ana": 95, "Cara": 91]

for (name, score) in scores {
    print("\(name): \(score)")
}
```

Output (tested with Swift 6.4):

```text
Ana: 95
Cara: 91
Ben: 88
```

**Fix:** Sort the dictionary keys or entries first if display order matters.

```swift
let scores = ["Ben": 88, "Ana": 95, "Cara": 91]

for name in scores.keys.sorted() {
    if let score = scores[name] {
        print("\(name): \(score)")
    }
}
```

Output (tested with Swift 6.4):

```text
Ana: 95
Ben: 88
Cara: 91
```

The corrected version works because the loop now uses a sorted list of keys instead of relying on raw dictionary iteration order.

### Mistake 3: Trying to access array items with an invalid index range

Some learners mix manual indexing with `for-in` and accidentally go past the end of the array. That can cause a runtime crash with an out-of-range error.

**Problem:** This code includes an index that does not exist in the array, so it can crash with `Fatal error: Index out of range`.

```swift
let names = ["Ava", "Leo", "Mia"]

for index in 0...names.count {
    print(names[index])
}
```

**Fix:** Either iterate over the array values directly or use a half-open range when indexing.

```swift
let names = ["Ava", "Leo", "Mia"]

for name in names {
    print(name)
}
```

Output (tested with Swift 6.4):

```text
Ava
Leo
Mia
```

The corrected version works because it avoids manual indexing entirely, which is both safer and clearer.

### Mistake 4: Needing the index but not using the right tool

A plain `for-in` loop gives you elements, not positions. Beginners sometimes try to invent counters manually when Swift already provides a clearer solution.

**Problem:** This code manages a separate counter by hand, which is easy to desynchronize from the collection being iterated.

```swift
let colors = ["Red", "Green", "Blue"]
var index = 0

for color in colors {
    print("\(index): \(color)")
    index += 1
}
```

Output (tested with Swift 6.4):

```text
0: Red
1: Green
2: Blue
```

**Fix:** Use `enumerated()` when you need both the index and the value.

```swift
let colors = ["Red", "Green", "Blue"]

for (index, color) in colors.enumerated() {
    print("\(index): \(color)")
}
```

Output (tested with Swift 6.4):

```text
0: Red
1: Green
2: Blue
```

The corrected version works because Swift provides the position and value together in a clean, reliable way.

## 7. Best Practices

### Practice 1: Iterate over values directly when possible

When you only need the elements themselves, loop over the collection directly rather than through indexes. This reduces noise and avoids out-of-range bugs.

Less-preferred approach:

```swift
let cities = ["Paris", "Tokyo", "Lima"]

for index in 0..<cities.count {
    print(cities[index])
}
```

Output (tested with Swift 6.4):

```text
Paris
Tokyo
Lima
```

Preferred approach:

```swift
let cities = ["Paris", "Tokyo", "Lima"]

for city in cities {
    print(city)
}
```

Output (tested with Swift 6.4):

```text
Paris
Tokyo
Lima
```

This style is easier to read and better matches Swift's collection design.

### Practice 2: Use meaningful loop variable names

The loop variable should describe the current item clearly. Good names make the body of the loop easier to understand.

Less-preferred approach:

```swift
let prices = [19.99, 5.50, 12.00]

for x in prices {
    print(x)
}
```

Output (tested with Swift 6.4):

```text
19.99
5.5
12.0
```

Preferred approach:

```swift
let prices = [19.99, 5.50, 12.00]

for price in prices {
    print("Price: \(price)")
}
```

Output (tested with Swift 6.4):

```text
Price: 19.99
Price: 5.5
Price: 12.0
```

A descriptive name makes the intent obvious and improves maintainability.

### Practice 3: Use where for simple filtering

If the filtering condition is small and directly related to the loop, a `where` clause can make the code cleaner than placing all logic inside the loop body.

Less-preferred approach:

```swift
for number in 1...10 {
    if number % 2 == 0 {
        print(number)
    }
}
```

Output (tested with Swift 6.4):

```text
2
4
6
8
10
```

Preferred approach:

```swift
for number in 1...10 where number % 2 == 0 {
    print(number)
}
```

Output (tested with Swift 6.4):

```text
2
4
6
8
10
```

This keeps the loop focused on exactly the values you want to process.

## 8. Limitations and Edge Cases

- A dictionary loop does not guarantee a user-friendly display order. Sort first if order matters.
- A set also does not provide a predictable display order for iteration in the way an array does.
- Using `0...array.count` for indexing is a common cause of `Fatal error: Index out of range`. Use direct iteration or `0..<array.count`.
- `enumerated()` provides integer offsets, which are useful for many collections, but string indexing in Swift has special rules and should not be treated like simple integer subscripting.
- If you need to stop early, you can use `break`. If you need to skip the current iteration, use `continue`.
- If the sequence is empty, the loop body does not run at all. This is normal and often useful.
- When you only want to repeat a fixed number of times and do not need the current value, use `_` to show that the value is intentionally unused.

> A common comparison is **Swift for-in vs while**. Use `for-in` when iterating over a known sequence such as an array or range. Use `while` when repetition depends on a condition that changes over time and is not tied to a specific collection.

## 9. Practical Mini Project

This small program uses several `for-in` patterns together. It loops through an array of quiz scores, calculates a total, prints whether each score passed, and then shows the class average.

```swift
let scores = [72, 88, 95, 61, 79]
var total = 0

for (index, score) in scores.enumerated() {
    total += score

    if score >= 70 {
        print("Student \(index + 1): \(score) - Pass")
    } else {
        print("Student \(index + 1): \(score) - Fail")
    }
}

let average = Double(total) / Double(scores.count)
print("Average score: \(average)")
```

Output (tested with Swift 6.4):

```text
Student 1: 72 - Pass
Student 2: 88 - Pass
Student 3: 95 - Pass
Student 4: 61 - Fail
Student 5: 79 - Pass
Average score: 79.0
```

This example shows direct collection processing, index-and-value iteration with `enumerated()`, and aggregation with a running total. It is a realistic pattern you will use often in command-line programs and app logic.

## 10. Key Points

- `for-in` is Swift's standard loop for iterating over ranges and collections.
- It works with arrays, dictionaries, sets, strings, and many other sequence types.
- Use `...` for a closed range and `..<` for a half-open range.
- Loop over values directly when you do not need indexes.
- Use `enumerated()` when you need both the position and the value.
- Use `where` for simple filtering during iteration.
- Do not rely on dictionary iteration order for sorted or fixed display output.
- Avoid manual indexing when direct iteration expresses the same logic more safely.

## 11. Practice Exercise

Try this exercise to test your understanding of Swift `for-in` loops.

- Create an array of five integers.
- Use a `for-in` loop to print each number.
- Use another `for-in` loop to calculate the sum of the numbers.
- Print only the odd numbers using a `where` clause.

**Expected output:** The program should print all values, the total sum, and then only the odd values.

**Hint:** Start with an array like `[3, 6, 9, 12, 15]` and keep a `sum` variable outside the loop.

```swift
let numbers = [3, 6, 9, 12, 15]
var sum = 0

print("All numbers:")
for number in numbers {
    print(number)
}

for number in numbers {
    sum += number
}

print("Sum: \(sum)")

print("Odd numbers:")
for number in numbers where number % 2 != 0 {
    print(number)
}
```

Output (tested with Swift 6.4):

```text
All numbers:
3
6
9
12
15
Sum: 45
Odd numbers:
3
9
15
```

## 12. Final Summary

Swift `for-in` loops give you a clean and safe way to repeat code over ranges and collections. They are one of the most important language features for everyday programming because they let you work directly with values instead of manually managing counters in many situations.

In this article, you saw the basic syntax, learned how to loop through ranges, arrays, dictionaries, and strings, and explored useful features such as `where` and `enumerated()`. You also saw common mistakes like choosing the wrong range operator or causing an `Index out of range` crash through manual indexing.

A strong next step is to learn related control-flow tools such as `while`, `break`, `continue`, and Swift collection methods like `map` and `filter`. Together, these will help you write loops that are not only correct, but also expressive and idiomatic.
