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

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.

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:

Do not use it when:

3. Basic Syntax or Core Idea

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.

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

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:

Ignoring the loop value

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

for _ in 1...3 {
    print("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.

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

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.

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

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

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.

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

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

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.

let word = "Swift"

for character in word {
    print(character)
}

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.

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

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

5. Practical Use Cases

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.

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

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

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

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.

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

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

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

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

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

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.

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.

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

for name in names {
    print(name)
}

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.

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

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

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

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

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

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:

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

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

Preferred approach:

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

for city in cities {
    print(city)
}

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:

let prices = [19.99, 5.50, 12.00]

for x in prices {
    print(x)
}

Preferred approach:

let prices = [19.99, 5.50, 12.00]

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

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:

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

Preferred approach:

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

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

8. Limitations and Edge Cases

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.

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)")

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

11. Practice Exercise

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

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.

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)
}

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.