Loops let a program repeat work: show every message in a chat, add up the prices in a basket, count down a timer, retry a download until it succeeds. Swift's main loop is for-in, which visits each item in a sequence such as a range of numbers, an array or the characters of a string.
Swift describes sequences of numbers with ranges: 1...5 includes five, while 1..<5 stops before it. For counting in steps or backwards there's stride. And for repeating "until something happens", there are while and repeat-while loops.
In this lesson you'll loop over ranges, collections and strings, count in steps, filter with where, get positions with enumerated(), and control loops with break, continue and labels.
for-in and ranges
for i in 1...5 {
print(i) // 1, 2, 3, 4, 5
}| Range | Values |
|---|---|
1...5 (closed) | 1, 2, 3, 4, 5 |
1..<5 (half-open) | 1, 2, 3, 4 |
(1...5).reversed() | 5, 4, 3, 2, 1 |
- The loop constant (
i) is created fresh each time and can't be changed inside the loop. - If you don't need it, write
_:for _ in 1...3 { print("Hip hip!") }. - Half-open ranges are perfect for array positions:
0..<array.count.
Looping over collections
let fruits = ["apple", "pear", "plum"]
for fruit in fruits { print(fruit) }
for (index, fruit) in fruits.enumerated() {
print("\(index + 1). \(fruit)")
}
for ch in "Swift" { print(ch) }enumerated() gives pairs of position and item, unpacked into two names. Looping directly over a collection is safer than counting positions yourself, because you can't go past the end. Add where to skip items: for n in numbers where n > 0.
stride
stride counts in steps of any size, forwards or backwards:
for t in stride(from: 0, to: 30, by: 10) { } // 0, 10, 20 (stops before 30)
for t in stride(from: 0, through: 30, by: 10) { } // 0, 10, 20, 30
for t in stride(from: 10, through: 0, by: -5) { } // 10, 5, 0to: excludes the end and through: includes it, just like ..< and .... Stride also works with Doubles: stride(from: 0.0, to: 1.0, by: 0.25).
while, repeat-while, break and continue
A while loop checks its condition before each pass; repeat { } while condition checks after, so it always runs at least once.
breakleaves the loop immediately.continueskips the rest of this pass and moves to the next.- In nested loops, label the outer loop (
outer: for ...) and usebreak outerto leave both.
var balance = 100.0
var years = 0
while balance < 200 {
balance *= 1.05
years += 1
}zip, indices and forEach
Sometimes you need to walk through two arrays side by side. zip pairs them up, item by item, and stops at the end of the shorter one:
let names = ["Ada", "Grace", "Linus"]
let scores = [90, 85]
for (name, score) in zip(names, scores) {
print("\(name): \(score)")
}
// Ada: 90
// Grace: 85 (Linus has no score, so he's skipped)When you need positions, loop over indices rather than writing 0..<array.count. It gives exactly the valid positions, and it's an empty loop when the array is empty: for i in names.indices { print(i, names[i]) }.
You'll also see forEach, which runs a closure for each item: names.forEach { print($0) }. It looks similar to for-in, but it behaves differently in two ways:
for-in | forEach | |
|---|---|---|
break and continue | Allowed | Not allowed |
return | Leaves the whole function | Skips only the current item |
Use for-in when you might stop early. forEach suits a short, single action at the end of a chain of operations.
Swift Loops Syntax
Loops
for i in 1...10 { }
for i in 0..<n { }
for item in array { }
for (i, item) in array.enumerated() { }
for n in numbers where n > 0 { }
for x in stride(from: 10, through: 0, by: -2) { }
while cond { }
repeat { } while cond
outer: for a in xs { for b in ys { break outer } }Swift Loops Summary
for item in sequenceloops over ranges, arrays, strings and more.1...5includes 5;1..<5stops before it;_ignores the loop value.- enumerated() gives position and item; where filters which items run.
- stride(from:to:by:) excludes the end and stride(from:through:by:) includes it; negative steps count down.
- while checks first, repeat-while runs at least once; break, continue and labels control loops.
Swift Loops Examples
Each example shows the code, the output it produces and what each part does.
A times table and a countdown
let n = 7
for i in 1...5 {
print("\(n) x \(i) = \(n * i)")
}
for s in stride(from: 10, through: 0, by: -5) {
print(s, terminator: " ")
}
print("Liftoff!")7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
10 5 0 Liftoff!Line-by-line explanation
- Line 21...5 includes both ends.
- Line 6stride with a negative step counts down; through includes 0.
- Line 7terminator keeps the countdown on one line.
Totals with enumerated and where
let prices = [2.50, 4.00, 1.25, 9.99]
var total = 0.0
for (i, price) in prices.enumerated() {
print("Item \(i + 1): £\(price)")
total += price
}
print("Total: £\(total)")
for price in prices where price < 2 {
print("Bargain: £\(price)")
}Item 1: £2.5
Item 2: £4.0
Item 3: £1.25
Item 4: £9.99
Total: £17.740000000000002
Bargain: £1.25Line-by-line explanation
- Line 4enumerated gives each position and price.
- Line 5Doubles print in their shortest form, so 2.50 shows as 2.5.
- Line 8Adding binary floating point numbers can leave a tiny error; format money for display, as the formatting lesson shows.
- Line 10where runs the loop body only for cheap items.
while, repeat-while, break and continue
var savings = 1000.0
var years = 0
while savings < 1500 {
savings *= 1.1
years += 1
}
print("Years to reach 1500: \(years)")
var attempts = 0
repeat {
attempts += 1
print("Attempt \(attempts)")
} while attempts < 2
for n in 1...10 {
if n % 2 == 0 { continue }
if n > 7 { break }
print(n, terminator: " ")
}
print()Years to reach 1500: 5
Attempt 1
Attempt 2
1 3 5 7 Line-by-line explanation
- Lines 3 to 6Grow by 10% a year: 1100, 1210, 1331, 1464.1, then 1610.51 after 5 years.
- Lines 10 to 13repeat-while runs the body first, then checks the condition.
- Line 16continue skips even numbers.
- Line 17break stops the loop once n passes 7.
Common Swift Loops Mistakes
Off by one with ranges
let items = ["a", "b", "c"]
for i in 0...items.count { print(items[i]) } // crash: index out of rangefor i in 0..<items.count { print(items[i]) }
// or simply: for item in items { print(item) }Counting down with a range
for i in 5...1 { print(i) } // crash: range requires lowerBound <= upperBoundfor i in (1...5).reversed() { print(i) }A while loop that never ends
var tries = 0
while tries < 3 {
print("Trying") // tries never changes
}var tries = 0
while tries < 3 {
print("Trying")
tries += 1
}Swift Loops in Real Projects
Loops in apps
Apps loop over lists of data to build screens, totals and summaries, though in SwiftUI the ForEach view does the looping for lists you display. Games loop every frame to update positions, and data-processing code loops over files and records. In practice, Swift developers also use collection methods like map, filter and reduce, covered in the closures lesson, to replace many hand-written loops.
Swift Loops FAQ
What is the difference between ... and ..< in Swift?
1...5 is a closed range that includes both ends, giving 1 to 5. 1..<5 is half-open and stops before the upper bound, giving 1 to 4. Use ..< with counts and array positions, so 0..<items.count covers every valid index.
How do I loop backwards in Swift?
Reverse a range with for i in (1...5).reversed(), or use stride(from: 5, through: 1, by: -1). A range like 5...1 isn't allowed: the program crashes because the lower bound is greater than the upper bound.
How do I get the index in a for-in loop?
Use enumerated(): for (index, item) in items.enumerated() gives each position, starting at 0, along with the item. If you only need positions, for i in items.indices is clearer.
Does Swift have a C-style for loop?
No. for (i = 0; i < 10; i++) was removed in Swift 3. Use for i in 0..<10 for counting, stride(from:to:by:) for other step sizes, and a while loop when the stopping rule is more complicated.
How do I break out of nested loops in Swift?
Put a label before the outer loop, such as outer: for row in grid, then write break outer inside the inner loop. A plain break would only leave the inner loop. continue outer works the same way to skip to the next outer pass.
Swift Loops Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the loop so it runs for 0, 1, 2 and 3.
for i in 04 { print(i) }
How many times does for _ in 1...3 { } run?
What does this print?
for x in stride(from: 1, to: 10, by: 3) { print(x, terminator: " ") }
Which loop always runs its body at least once?
What does this print?
var total = 0
for n in 1...6 where n != 4 {
total += n
}
print(total)
Swift Loops Quiz
5 questions to check what you learned.
Does the range
1...3include 3?- Yes
- No
- Only in while loops
- Only with stride
What does
enumerated()give in a for-in loop?- Only positions
- A sorted copy
- Pairs of position and item
- The count
What does
continuedo?- Ends the loop
- Skips to the next pass of the loop
- Restarts from the beginning
- Pauses the app
How do you count 10, 8, 6 ... 0?
- for i in stride(from: 10, through: 0, by: -2)
- for i in 10...0
- for i in 0...10 by 2
- for i in (0..<10).step(2)
What happens with
for i in 5...1?- It counts down
- It does nothing
- It compiles but warns
- The program crashes, because a range's lower bound can't be above its upper bound