Skip to content

Swift Loops - Repeating Actions Efficiently

Welcome to Swift Loops! Loops are one of the most powerful features in programmingโ€”they allow you to repeat actions efficiently without writing the same code over and over. In this guide, weโ€™ll explore all the different types of loops in Swift and learn when to use each one.

What Are Loops?

Loops are control flow structures that repeat a block of code multiple times. Instead of writing:

print("Hello 1")
print("Hello 2")
print("Hello 3")
print("Hello 4")
print("Hello 5")

You can write:

for number in 1...5 {
print("Hello \(number)")
}

Much cleaner, right? Loops save you time, reduce errors, and make your code more maintainable.

For-In Loops

The for-in loop is the most commonly used loop in Swift. It iterates over sequences like arrays, ranges, dictionaries, and strings.

Basic For-In Loop with Ranges

// Loop from 1 to 5 (inclusive)
for number in 1...5 {
print(number)
}
// Output: 1, 2, 3, 4, 5
// Loop from 1 to 4 (5 is excluded)
for number in 1..<5 {
print(number)
}
// Output: 1, 2, 3, 4

Counting Backwards

// Count down from 5 to 1
for number in (1...5).reversed() {
print(number)
}
// Output: 5, 4, 3, 2, 1
// Countdown
for count in (1...10).reversed() {
if count == 1 {
print("๐Ÿš€ Blast off!")
} else {
print(count)
}
}

Using Stride for Custom Steps

// Count by 2s
for number in stride(from: 0, to: 10, by: 2) {
print(number)
}
// Output: 0, 2, 4, 6, 8
// Count by 5s from 0 to 50 (inclusive)
for number in stride(from: 0, through: 50, by: 5) {
print(number)
}
// Output: 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50
// Count backwards by 3s
for number in stride(from: 20, through: 0, by: -3) {
print(number)
}
// Output: 20, 17, 14, 11, 8, 5, 2

Looping Over Arrays

let fruits = ["Apple", "Banana", "Cherry", "Mango"]
// Simple iteration
for fruit in fruits {
print("I like \(fruit)s")
}
// Output:
// I like Apples
// I like Bananas
// I like Cherries
// I like Mangos
// With index using enumerated()
for (index, fruit) in fruits.enumerated() {
print("\(index + 1). \(fruit)")
}
// Output:
// 1. Apple
// 2. Banana
// 3. Cherry
// 4. Mango

Looping Over Dictionaries

let studentGrades = [
"Alice": 95,
"Bob": 87,
"Charlie": 92
]
// Loop over key-value pairs
for (student, grade) in studentGrades {
print("\(student) scored \(grade)")
}
// Output (order may vary):
// Alice scored 95
// Bob scored 87
// Charlie scored 92
// Loop over keys only
for student in studentGrades.keys {
print(student)
}
// Loop over values only
for grade in studentGrades.values {
print("Grade: \(grade)")
}
// Sorted by keys
for (student, grade) in studentGrades.sorted(by: { $0.key < $1.key }) {
print("\(student): \(grade)")
}
// Output (alphabetical):
// Alice: 95
// Bob: 87
// Charlie: 92

Looping Over Strings

let message = "Hello"
// Loop over characters
for character in message {
print(character)
}
// Output: H, e, l, l, o
// With index
for (index, character) in message.enumerated() {
print("Character \(index): \(character)")
}

Underscore for Unused Values

If you donโ€™t need the loop variable, use an underscore:

// Print "Hello" 5 times
for _ in 1...5 {
print("Hello!")
}
// Generate random numbers without using the loop variable
for _ in 1...3 {
let random = Int.random(in: 1...100)
print("Random number: \(random)")
}

Nested For Loops

// Multiplication table
for i in 1...5 {
for j in 1...5 {
print("\(i) ร— \(j) = \(i * j)")
}
print("---")
}
// Create a grid pattern
for row in 1...3 {
for col in 1...4 {
print("(\(row),\(col))", terminator: " ")
}
print() // New line
}
// Output:
// (1,1) (1,2) (1,3) (1,4)
// (2,1) (2,2) (2,3) (2,4)
// (3,1) (3,2) (3,3) (3,4)

While Loops

While loops continue executing as long as a condition is true. Theyโ€™re perfect when you donโ€™t know how many iterations youโ€™ll need in advance.

Basic While Loop

var count = 1
while count <= 5 {
print("Count: \(count)")
count += 1
}
// Output: Count: 1, Count: 2, Count: 3, Count: 4, Count: 5

While Loop with User Input Simulation

var attempts = 0
var password = ""
let correctPassword = "secret123"
while password != correctPassword && attempts < 3 {
attempts += 1
print("Attempt \(attempts): Enter password")
// In real app, you'd get user input here
password = attempts == 2 ? "secret123" : "wrong"
}
if password == correctPassword {
print("โœ… Access granted!")
} else {
print("โŒ Too many failed attempts")
}

While Loop for Game Logic

var health = 100
var round = 0
while health > 0 {
round += 1
let damage = Int.random(in: 10...30)
health -= damage
print("Round \(round): Took \(damage) damage. Health: \(max(health, 0))")
if health <= 0 {
print("๐Ÿ’€ Game Over!")
}
}

Infinite Loop with Break

var sum = 0
var number = 1
while true {
sum += number
number += 1
if sum >= 100 {
print("Sum reached \(sum)")
break
}
}

Repeat-While Loops

Repeat-while loops are similar to while loops, but they check the condition AFTER executing the code block. This means they always execute at least once.

Basic Repeat-While

var count = 1
repeat {
print("Count: \(count)")
count += 1
} while count <= 5
// Output: Count: 1, Count: 2, Count: 3, Count: 4, Count: 5

Key Difference: Runs At Least Once

// While loop - may not run at all
var x = 10
while x < 5 {
print("This will never print")
x += 1
}
// No output
// Repeat-while - always runs at least once
var y = 10
repeat {
print("This prints once: \(y)")
y += 1
} while y < 5
// Output: This prints once: 10
var choice = 0
var menuActive = true
repeat {
print("""
--- Menu ---
1. Start Game
2. Settings
3. Exit
Choose an option:
""")
// Simulate user choice
choice = Int.random(in: 1...3)
print("Selected: \(choice)")
switch choice {
case 1:
print("๐ŸŽฎ Starting game...")
case 2:
print("โš™๏ธ Opening settings...")
case 3:
print("๐Ÿ‘‹ Goodbye!")
menuActive = false
default:
print("โŒ Invalid choice")
}
} while menuActive

Input Validation

var age = 0
repeat {
// Simulate getting age input
age = Int.random(in: -5...120)
print("Entered age: \(age)")
if age < 0 || age > 120 {
print("โŒ Please enter a valid age (0-120)")
}
} while age < 0 || age > 120
print("โœ… Valid age: \(age)")

Loop Control: Break and Continue

Break and continue give you fine control over loop execution.

Break - Exit the Loop

The break statement immediately exits the loop:

// Find first even number
let numbers = [1, 3, 5, 8, 9, 10, 11]
for number in numbers {
if number % 2 == 0 {
print("Found first even number: \(number)")
break
}
}
// Output: Found first even number: 8
// Search for a name
let names = ["Alice", "Bob", "Charlie", "David"]
let searchName = "Charlie"
for name in names {
if name == searchName {
print("โœ… Found \(searchName)!")
break
}
print("Checking \(name)...")
}
// Output:
// Checking Alice...
// Checking Bob...
// โœ… Found Charlie!

Continue - Skip to Next Iteration

The continue statement skips the rest of the current iteration and moves to the next one:

// Print only odd numbers
for number in 1...10 {
if number % 2 == 0 {
continue // Skip even numbers
}
print(number)
}
// Output: 1, 3, 5, 7, 9
// Process valid items only
let scores = [85, -1, 92, 105, 78, -5, 88]
for score in scores {
if score < 0 || score > 100 {
print("Skipping invalid score: \(score)")
continue
}
print("Valid score: \(score)")
}
// Output:
// Valid score: 85
// Skipping invalid score: -1
// Valid score: 92
// Skipping invalid score: 105
// Valid score: 78
// Skipping invalid score: -5
// Valid score: 88

Break in Nested Loops

Break only exits the innermost loop:

// Find first match in 2D grid
let grid = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
var found = false
for row in grid {
for number in row {
if number == 5 {
print("Found 5!")
found = true
break // Only breaks inner loop
}
}
if found {
break // Break outer loop
}
}

Labeled Statements

Use labels to break out of outer loops:

outerLoop: for i in 1...3 {
for j in 1...3 {
if i == 2 && j == 2 {
print("Breaking out of both loops at (\(i),\(j))")
break outerLoop
}
print("(\(i),\(j))")
}
}
// Output:
// (1,1)
// (1,2)
// (1,3)
// (2,1)
// Breaking out of both loops at (2,2)

Practical Examples

Example 1: Sum Calculator

let numbers = [5, 10, 15, 20, 25]
var sum = 0
for number in numbers {
sum += number
}
print("Sum: \(sum)") // Output: Sum: 75
// Calculate average
let average = Double(sum) / Double(numbers.count)
print("Average: \(average)") // Output: Average: 15.0

Example 2: Factorial Calculator

func factorial(of n: Int) -> Int {
guard n >= 0 else { return 0 }
var result = 1
for i in 1...n {
result *= i
}
return result
}
print("5! = \(factorial(of: 5))") // Output: 5! = 120
print("10! = \(factorial(of: 10))") // Output: 10! = 3628800

Example 3: Fibonacci Sequence

func fibonacci(count: Int) -> [Int] {
guard count > 0 else { return [] }
var sequence = [0, 1]
if count <= 2 {
return Array(sequence.prefix(count))
}
for _ in 2..<count {
let next = sequence[sequence.count - 1] + sequence[sequence.count - 2]
sequence.append(next)
}
return sequence
}
print(fibonacci(count: 10))
// Output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Example 4: Prime Number Checker

func isPrime(_ number: Int) -> Bool {
guard number > 1 else { return false }
guard number > 3 else { return true }
if number % 2 == 0 || number % 3 == 0 {
return false
}
var i = 5
while i * i <= number {
if number % i == 0 || number % (i + 2) == 0 {
return false
}
i += 6
}
return true
}
// Find all primes up to 50
var primes: [Int] = []
for number in 2...50 {
if isPrime(number) {
primes.append(number)
}
}
print("Primes up to 50: \(primes)")
// Output: Primes up to 50: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Example 5: Pattern Printing

// Right triangle
print("Right Triangle:")
for i in 1...5 {
for _ in 1...i {
print("*", terminator: "")
}
print()
}
// Output:
// *
// **
// ***
// ****
// *****
// Pyramid
print("\nPyramid:")
let height = 5
for i in 1...height {
// Print spaces
for _ in 1...(height - i) {
print(" ", terminator: "")
}
// Print stars
for _ in 1...(2 * i - 1) {
print("*", terminator: "")
}
print()
}
// Output:
// *
// ***
// *****
// *******
// *********

Example 6: Shopping Cart Total

struct Product {
let name: String
let price: Double
let quantity: Int
}
let cart = [
Product(name: "iPhone", price: 999.99, quantity: 1),
Product(name: "AirPods", price: 179.99, quantity: 2),
Product(name: "Case", price: 29.99, quantity: 1)
]
var total = 0.0
print("Shopping Cart:")
print("---")
for product in cart {
let itemTotal = product.price * Double(product.quantity)
total += itemTotal
print("\(product.name) ร— \(product.quantity): $\(itemTotal)")
}
print("---")
print("Total: $\(total)")
// Output:
// Shopping Cart:
// ---
// iPhone ร— 1: $999.99
// AirPods ร— 2: $359.98
// Case ร— 1: $29.99
// ---
// Total: $1389.96

Example 7: Password Strength Checker

func checkPasswordStrength(_ password: String) -> String {
var score = 0
// Check length
if password.count >= 8 {
score += 1
}
if password.count >= 12 {
score += 1
}
// Check for different character types
var hasUpper = false
var hasLower = false
var hasDigit = false
var hasSpecial = false
for character in password {
if character.isUppercase { hasUpper = true }
if character.isLowercase { hasLower = true }
if character.isNumber { hasDigit = true }
if !character.isLetter && !character.isNumber { hasSpecial = true }
}
if hasUpper { score += 1 }
if hasLower { score += 1 }
if hasDigit { score += 1 }
if hasSpecial { score += 1 }
switch score {
case 0...2: return "โŒ Weak"
case 3...4: return "โš ๏ธ Medium"
case 5...6: return "โœ… Strong"
default: return "๐Ÿ”’ Very Strong"
}
}
print(checkPasswordStrength("abc")) // โŒ Weak
print(checkPasswordStrength("Password123")) // โš ๏ธ Medium
print(checkPasswordStrength("P@ssw0rd123!")) // ๐Ÿ”’ Very Strong

Example 8: Array Search and Filter

let numbers = [3, 7, 12, 5, 18, 9, 14, 22, 6]
// Find all even numbers
var evenNumbers: [Int] = []
for number in numbers {
if number % 2 == 0 {
evenNumbers.append(number)
}
}
print("Even numbers: \(evenNumbers)") // [12, 18, 14, 22, 6]
// Find numbers greater than 10
var largeNumbers: [Int] = []
for number in numbers {
if number > 10 {
largeNumbers.append(number)
}
}
print("Numbers > 10: \(largeNumbers)") // [12, 18, 14, 22]
// Count numbers in range
var count = 0
for number in numbers {
if number >= 5 && number <= 15 {
count += 1
}
}
print("Numbers between 5-15: \(count)") // 5

When to Use Each Loop Type

Use For-In When:

โœ… You know the number of iterations
โœ… Iterating over a collection (array, dictionary, range)
โœ… You need the index or value from the collection
โœ… Most common loop type - use by default

Examples: Processing array items, counting in ranges, iterating dictionaries

Use While When:

โœ… The number of iterations is unknown
โœ… Youโ€™re waiting for a condition to be met
โœ… Condition needs to be checked before first iteration
โœ… Implementing game loops or event loops

Examples: User input validation, game loops, waiting for events

Use Repeat-While When:

โœ… Code must execute at least once
โœ… Validation happens after the action
โœ… Menu systems and prompts

Examples: Menu systems, input prompts, retry logic

Best Practices

1. Choose the Right Loop Type

// โœ… Use for-in for known iterations
for i in 1...10 {
print(i)
}
// โŒ Don't use while for simple counting
var i = 1
while i <= 10 {
print(i)
i += 1
}

2. Use Meaningful Variable Names

// โŒ Poor naming
for i in names {
print(i)
}
// โœ… Clear naming
for name in names {
print(name)
}

3. Avoid Infinite Loops

// โŒ Dangerous - infinite loop
// while true {
// print("This never stops!")
// }
// โœ… Safe - has exit condition
var count = 0
while count < 10 {
print(count)
count += 1
}

4. Use Underscore for Unused Variables

// โŒ Unused variable warning
for index in 1...5 {
print("Hello")
}
// โœ… Clean with underscore
for _ in 1...5 {
print("Hello")
}

5. Keep Loop Bodies Simple

// โŒ Complex loop body
for number in numbers {
if number > 0 {
if number % 2 == 0 {
if number < 100 {
// Do something
}
}
}
}
// โœ… Use guard or continue for early exit
for number in numbers {
guard number > 0, number % 2 == 0, number < 100 else {
continue
}
// Do something
}

Common Mistakes to Avoid

1. Modifying Collection While Iterating

var numbers = [1, 2, 3, 4, 5]
// โŒ Don't modify while iterating
// for number in numbers {
// numbers.append(number * 2) // Crash or unexpected behavior!
// }
// โœ… Create a new array
var doubled: [Int] = []
for number in numbers {
doubled.append(number * 2)
}

2. Off-by-One Errors

let items = ["A", "B", "C"]
// โŒ Index out of bounds
// for i in 0...items.count {
// print(items[i]) // Crash on last iteration!
// }
// โœ… Correct range
for i in 0..<items.count {
print(items[i])
}
// โœ… Better - use for-in directly
for item in items {
print(item)
}

3. Forgetting to Update Loop Condition

// โŒ Infinite loop - forgot to increment
// var i = 0
// while i < 10 {
// print(i)
// // Forgot: i += 1
// }
// โœ… Proper update
var i = 0
while i < 10 {
print(i)
i += 1
}

4. Unnecessary Nested Loops

let numbers = [1, 2, 3, 4, 5]
// โŒ Inefficient O(nยฒ)
var doubles: [Int] = []
for number in numbers {
for _ in 1...1 {
doubles.append(number * 2)
}
}
// โœ… Simple O(n)
var betterDoubles: [Int] = []
for number in numbers {
betterDoubles.append(number * 2)
}

Performance Tips

1. Use Ranges Instead of Arrays When Possible

// โš ๏ธ Creates an array in memory
let numbers = Array(1...1000000)
for number in numbers {
// Process
}
// โœ… Uses lazy evaluation
for number in 1...1000000 {
// Process
}

2. Break Early When Found

let numbers = [1, 3, 5, 7, 9, 2, 4, 6, 8]
// โš ๏ธ Continues even after finding
var foundEven = false
for number in numbers {
if number % 2 == 0 {
foundEven = true
}
}
// โœ… Exits immediately
for number in numbers {
if number % 2 == 0 {
print("Found even: \(number)")
break
}
}

Summary

Loops are essential for efficient programming. Hereโ€™s what we covered:

For-In Loops ๐Ÿ”„

  • Most common loop type
  • Iterate over ranges, arrays, dictionaries
  • Use enumerated() for indices
  • Use stride() for custom steps

While Loops โณ

  • Condition checked before execution
  • Unknown number of iterations
  • Great for event-driven logic

Repeat-While Loops ๐Ÿ”

  • Executes at least once
  • Condition checked after execution
  • Perfect for menus and input validation

Loop Control ๐ŸŽฎ

  • break: Exit the loop immediately
  • continue: Skip to next iteration
  • Use labels for nested loops

Next Steps

Congratulations! Youโ€™ve mastered loops in Swift! ๐ŸŽ‰

Tomorrow, weโ€™ll explore:

  • Topic 9: Functions
  • Function declaration and calling
  • Parameters and return values
  • Argument labels
  • Variadic parameters

Practice Exercises

Try these to reinforce your learning:

  1. Write a loop that prints the multiplication table for any number
  2. Create a function that finds the largest number in an array using a loop
  3. Build a guessing game using while loops
  4. Generate a pyramid pattern using nested for loops
  5. Write a loop that reverses a string manually
  6. Calculate the sum of all even numbers from 1 to 100
  7. Create a function that checks if a number is prime using loops

Master loops and youโ€™ll write efficient, powerful code! ๐Ÿš€

Remember: Choose the right loop for the job, and your code will be both clean and performant.