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.
- 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 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:
- 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.
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
- 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.
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 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.
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
- 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.
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.