Welcome back, aspiring Swift developer! In the previous chapters, we laid the groundwork by understanding what Swift is, how to set up your environment, and how to work with variables, constants, and basic data types. Now, it’s time to bring our code to life and make it do things!

This chapter is all about teaching your programs how to perform calculations, make decisions, and repeat actions. We’ll explore operators to manipulate values, conditionals to execute different code paths based on circumstances, and loops to automate repetitive tasks. These are the core building blocks that transform static data into dynamic, interactive applications.

By the end of this chapter, you’ll be able to write Swift code that responds intelligently to different inputs and efficiently handles repetitive operations, setting a strong foundation for building more complex application logic. Get ready to make your code smart and efficient!

Prerequisites

Before we dive in, make sure you’re comfortable with:

  • Declaring variables and constants (var and let).
  • Understanding basic Swift data types like Int, Double, Bool, and String.
  • Using Xcode Playgrounds for quick experimentation.

We’ll be using Swift version 5.10, the latest stable release as of February 2026, which continues to refine performance and safety, especially with ongoing work towards Swift 6’s concurrency model. The core language features covered here are highly stable across Swift versions.

Core Concepts

Let’s break down these essential concepts one by one.

1. Operators: The Action Verbs of Swift

Think of operators as special symbols that perform checks, assignments, or mathematical operations on one or more values. These values are called operands. Just like verbs in a sentence, operators tell your program what action to take.

a. Arithmetic Operators

These are likely familiar from basic math. They perform mathematical calculations.

  • + (addition)
  • - (subtraction)
  • * (multiplication)
  • / (division)
  • % (remainder, or modulo)

Let’s see them in action.

// Arithmetic Operators in Swift

// 1. Addition
let sum = 10 + 5
print("Sum: \(sum)") // Output: Sum: 15

// 2. Subtraction
let difference = 20 - 7
print("Difference: \(difference)") // Output: Difference: 13

// 3. Multiplication
let product = 4 * 6
print("Product: \(product)") // Output: Product: 24

// 4. Division
let quotient = 25 / 5
print("Quotient: \(quotient)") // Output: Quotient: 5

// Integer division truncates the decimal part
let integerDivision = 10 / 3
print("Integer Division: \(integerDivision)") // Output: Integer Division: 3 (not 3.33)

// To get decimal division, ensure at least one operand is a Double
let decimalDivision = 10.0 / 3
print("Decimal Division: \(decimalDivision)") // Output: Decimal Division: 3.3333333333333335

// 5. Remainder (Modulo)
// This operator returns the remainder after division.
let remainder = 10 % 3
print("Remainder of 10 / 3: \(remainder)") // Output: Remainder of 10 / 3: 1 (10 = 3*3 + 1)

let anotherRemainder = 12 % 4
print("Remainder of 12 / 4: \(anotherRemainder)") // Output: Remainder of 12 / 4: 0

Why is 10 / 3 different from 10.0 / 3? This is a crucial concept related to type safety. Swift is strict about types. When both operands are Ints, Swift performs integer division, resulting in an Int. If one or both operands are Doubles, it performs floating-point division, resulting in a Double. This prevents unexpected loss of precision.

b. Assignment Operators

These operators are used to assign a value to a variable or constant. The most basic is the = operator.

  • = (assignment)
  • += (add and assign)
  • -= (subtract and assign)
  • *= (multiply and assign)
  • /= (divide and assign)
  • %= (remainder and assign)

These shorthand operators are super common for updating a variable’s value.

// Assignment Operators in Swift

var score = 100 // Basic assignment using =

// Add and assign
score += 50 // Equivalent to: score = score + 50
print("Score after adding 50: \(score)") // Output: Score after adding 50: 150

// Subtract and assign
score -= 20 // Equivalent to: score = score - 20
print("Score after subtracting 20: \(score)") // Output: Score after subtracting 20: 130

// Multiply and assign
var multiplier = 2
multiplier *= 3 // Equivalent to: multiplier = multiplier * 3
print("Multiplier after multiplying by 3: \(multiplier)") // Output: Multiplier after multiplying by 3: 6

// Divide and assign
var quantity = 100
quantity /= 10 // Equivalent to: quantity = quantity / 10
print("Quantity after dividing by 10: \(quantity)") // Output: Quantity after dividing by 10: 10

// Remainder and assign
var cookies = 17
cookies %= 5 // Equivalent to: cookies = cookies % 5
print("Remaining cookies after sharing among 5: \(cookies)") // Output: Remaining cookies after sharing among 5: 2

c. Comparison Operators

These operators compare two values and return a Bool (either true or false). They are fundamental for making decisions in your code.

  • == (equal to)
  • != (not equal to)
  • > (greater than)
  • < (less than)
  • >= (greater than or equal to)
  • <= (less than or equal to)
// Comparison Operators in Swift

let temperature = 25
let limit = 20

print("Is temperature equal to limit? \(temperature == limit)") // Output: false
print("Is temperature not equal to limit? \(temperature != limit)") // Output: true
print("Is temperature greater than limit? \(temperature > limit)") // Output: true
print("Is temperature less than limit? \(temperature < limit)") // Output: false
print("Is temperature greater than or equal to limit? \(temperature >= limit)") // Output: true
print("Is temperature less than or equal to limit? \(temperature <= limit)") // Output: false

let name1 = "Alice"
let name2 = "Bob"
print("Are names equal? \(name1 == name2)") // Output: false

Important: Notice the double equals == for comparison. A single equals = is for assignment. This is a common beginner mistake!

d. Logical Operators

Logical operators combine or modify boolean (true/false) conditions.

  • && (logical AND): Returns true if both conditions are true.
  • || (logical OR): Returns true if at least one condition is true.
  • ! (logical NOT): Inverts a boolean value (true becomes false, false becomes true).
// Logical Operators in Swift

let hasLicense = true
let isSober = true
let isDaytime = false

// Logical AND (&&)
// Both conditions must be true for the result to be true
let canDrive = hasLicense && isSober
print("Can drive? \(canDrive)") // Output: Can drive? true

let canDriveAtNight = canDrive && !isDaytime // Using logical NOT
print("Can drive at night? \(canDriveAtNight)") // Output: Can drive at night? true (since !isDaytime is true)

// Logical OR (||)
// At least one condition must be true for the result to be true
let hasPermission = false
let isManager = true
let canAccessRestrictedArea = hasPermission || isManager
print("Can access restricted area? \(canAccessRestrictedArea)") // Output: Can access restricted area? true

// Logical NOT (!)
// Inverts the boolean value
let isRaining = true
let notRaining = !isRaining
print("Is it not raining? \(notRaining)") // Output: Is it not raining? false

e. Range Operators

Swift provides convenient ways to define a range of values. These are often used with loops.

  • Closed Range Operator (...): Includes both the starting and ending values.
  • Half-Open Range Operator (..<): Includes the starting value but excludes the ending value.
// Range Operators in Swift

// Closed Range (includes both ends)
for i in 1...5 {
    print("Closed range number: \(i)") // Prints 1, 2, 3, 4, 5
}

// Half-Open Range (excludes the end)
for j in 0..<5 {
    print("Half-open range number: \(j)") // Prints 0, 1, 2, 3, 4
}

f. Ternary Conditional Operator

This is a shorthand for an if-else statement that returns one of two values based on a condition. It has three parts: condition ? valueIfTrue : valueIfFalse.

// Ternary Conditional Operator in Swift

let userLoggedIn = true
let welcomeMessage = userLoggedIn ? "Welcome back!" : "Please log in."
print(welcomeMessage) // Output: Welcome back!

let currentTemperature = 18
let clothingSuggestion = currentTemperature > 20 ? "Wear light clothes." : "Bring a jacket."
print(clothingSuggestion) // Output: Bring a jacket.

While concise, use the ternary operator judiciously. For complex conditions or actions, a full if-else statement is often more readable.

2. Conditionals: Making Decisions

Conditionals allow your program to execute different blocks of code based on whether certain conditions are true or false. This is where your app starts to feel “smart” and responsive!

a. if Statement

The simplest conditional, it executes code only if a condition is true.

// Basic if statement

let isRaining = true

if isRaining {
    print("Don't forget your umbrella!")
}
// Output: Don't forget your umbrella!

let currentHour = 10
if currentHour < 12 {
    print("Good morning!")
}
// Output: Good morning!

Notice how the code inside the curly braces {} only runs if isRaining is true or currentHour < 12 is true.

b. if-else Statement

This provides an alternative path. If the if condition is false, the code inside the else block is executed.

// if-else statement

let temperature = 22

if temperature > 25 {
    print("It's hot outside!")
} else {
    print("It's a pleasant temperature.")
}
// Output: It's a pleasant temperature.

let isLoggedIn = false
if isLoggedIn {
    print("Welcome to your dashboard!")
} else {
    print("Please log in to continue.")
}
// Output: Please log in to continue.

c. if-else if-else Chain

When you have multiple possible conditions to check, you can chain else if statements. Swift checks conditions in order, from top to bottom, and executes the first block whose condition is true. If none of the if or else if conditions are met, the final else block (if present) is executed.

Let’s visualize this flow:

flowchart TD Start --> CheckConditionA{Is Condition A true?} CheckConditionA -->|\1| ActionA[Perform Action A] CheckConditionA -->|\1| CheckConditionB{Is Condition B true?} CheckConditionB -->|\1| ActionB[Perform Action B] CheckConditionB -->|\1| ActionC[Perform Action C] ActionA --> End ActionB --> End ActionC --> End
// if-else if-else chain

let grade = 85

if grade >= 90 {
    print("Grade: A")
} else if grade >= 80 {
    print("Grade: B")
} else if grade >= 70 {
    print("Grade: C")
} else if grade >= 60 {
    print("Grade: D")
} else {
    print("Grade: F")
}
// Output: Grade: B

let dayOfWeek = "Sunday"

if dayOfWeek == "Saturday" || dayOfWeek == "Sunday" {
    print("It's the weekend!")
} else if dayOfWeek == "Friday" {
    print("Almost there! Happy Friday!")
} else {
    print("It's a weekday.")
}
// Output: It's the weekend!

d. switch Statement

The switch statement is a powerful alternative to if-else if-else chains when you’re checking a single value against multiple possible cases. Swift’s switch statements are very flexible and safe.

Key features of Swift’s switch:

  • Exhaustive: Every possible value for the type being switched must be covered. If not, Swift will give a compile-time error. You can use a default case to cover any unhandled values.
  • No Implicit Fallthrough: Unlike some other languages, Swift’s switch cases do not “fall through” to the next case by default. Once a case matches, the code executes and the switch statement finishes. If you do want fallthrough, you must explicitly use the fallthrough keyword (though it’s rare to need it).
  • Pattern Matching: switch can do much more than just check for equality. It can match against ranges, tuples, type casts, and even bind values to temporary constants/variables (using case let).
// Basic switch statement

let fruit = "Apple"

switch fruit {
case "Apple":
    print("This is a red fruit.")
case "Banana":
    print("This is a yellow fruit.")
case "Orange":
    print("This is a citrus fruit.")
default: // The default case is mandatory if not all possible values are explicitly handled
    print("Unknown fruit.")
}
// Output: This is a red fruit.

// Switch with ranges and value binding
let score = 92

switch score {
case 90...100:
    print("Excellent! You got an A.")
case 80..<90:
    print("Very good! You got a B.")
case 70..<80:
    print("Good job! You got a C.")
case let s where s < 70: // Using 'case let' to bind the value and 'where' for additional conditions
    print("You got an F with score \(s). Time to review!")
default: // This default is theoretically unreachable with the ranges above, but good practice
    print("Invalid score.")
}
// Output: Excellent! You got an A.

// Switch with multiple values in a single case
let character = "e"

switch character {
case "a", "e", "i", "o", "u":
    print("\(character) is a vowel.")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
    print("\(character) is a consonant.")
default:
    print("\(character) is not a letter.")
}
// Output: e is a vowel.

The switch statement is incredibly powerful for writing clean and readable code when dealing with multiple conditions on a single value.

3. Loops: Repeating Actions

Loops allow you to execute a block of code multiple times. This is essential for tasks like processing items in a list, performing calculations until a condition is met, or simply repeating an animation.

a. for-in Loop

This loop iterates over a sequence, such as a range of numbers, items in an array, or characters in a string. It’s the most common loop in Swift.

// for-in loop with a range

print("Counting from 1 to 3:")
for i in 1...3 {
    print(i)
}
// Output:
// 1
// 2
// 3

// for-in loop with an array (we'll cover arrays more in a later chapter)
let fruits = ["Apple", "Banana", "Cherry"]
print("\nMy favorite fruits are:")
for fruitName in fruits {
    print(fruitName)
}
// Output:
// My favorite fruits are:
// Apple
// Banana
// Cherry

// If you don't need the value, you can use an underscore `_`
print("\nRepeating a message 2 times:")
for _ in 0..<2 {
    print("Hello Swift!")
}
// Output:
// Hello Swift!
// Hello Swift!

b. while Loop

A while loop repeatedly executes a block of code as long as a condition remains true. The condition is checked before each iteration.

Crucial Warning: Be careful with while loops! If the condition never becomes false, you’ll create an infinite loop, which will cause your program to freeze. Always ensure there’s a way for the condition to eventually become false.

// while loop

var countdown = 3
print("Starting countdown:")
while countdown > 0 {
    print(countdown)
    countdown -= 1 // This line is crucial to eventually make 'countdown > 0' false
}
print("Blast off!")
// Output:
// Starting countdown:
// 3
// 2
// 1
// Blast off!

var energyLevel = 10
while energyLevel > 0 {
    print("Current energy: \(energyLevel)")
    energyLevel -= 2
    if energyLevel <= 4 {
        print("Feeling tired, need a break soon...")
    }
}
print("Out of energy!")
// Output:
// Current energy: 10
// Current energy: 8
// Current energy: 6
// Current energy: 4
// Feeling tired, need a break soon...
// Current energy: 2
// Feeling tired, need a break soon...
// Out of energy!

c. repeat-while Loop

Similar to while, but the condition is checked after the loop body is executed. This means the code block inside a repeat-while loop is always executed at least once.

// repeat-while loop

var attempts = 0
let maxAttempts = 3
var success = false

repeat {
    attempts += 1
    print("Attempt \(attempts) to connect...")

    // Simulate connection attempt
    if attempts == maxAttempts {
        success = true
    }

} while !success && attempts < maxAttempts

if success {
    print("Connection established after \(attempts) attempts.")
} else {
    print("Failed to connect after \(maxAttempts) attempts.")
}
// Output (if maxAttempts is 3, success=true):
// Attempt 1 to connect...
// Attempt 2 to connect...
// Attempt 3 to connect...
// Connection established after 3 attempts.

// Example showing it runs at least once
var x = 0
repeat {
    print("This will print at least once. x = \(x)")
    x += 1
} while x < 0 // Condition is false, but loop ran once
// Output: This will print at least once. x = 0

d. break and continue Statements

You can control the flow of loops using break and continue.

  • break: Immediately ends the execution of the entire loop and continues with the code after the loop.
  • continue: Stops the current iteration of the loop and starts the next iteration.
// break and continue in loops

print("Using 'continue':")
for i in 1...5 {
    if i == 3 {
        continue // Skip printing 3, go to next iteration
    }
    print(i)
}
// Output:
// 1
// 2
// 4
// 5

print("\nUsing 'break':")
for i in 1...5 {
    if i == 3 {
        break // Stop the loop entirely when i is 3
    }
    print(i)
}
// Output:
// 1
// 2

Mini-Challenge: The Daily Planner

Let’s put your new knowledge into practice!

Challenge: Create a simple “Daily Planner” program that:

  1. Asks the user (or simulates input) for the current hour (as an Int, 0-23) and if it’s a weekday (Bool).
  2. Uses an if-else if-else chain to determine the time of day and suggest an activity:
    • 0-5 (night): “It’s late, get some rest!”
    • 6-8 (early morning): “Good morning! Time for breakfast.”
    • 9-12 (morning): “Morning routine or work/study.”
    • 13-17 (afternoon): “Afternoon tasks or break time.”
    • 18-20 (evening): “Dinner and relax.”
    • 21-23 (late evening): “Wind down for the night.”
  3. If it’s a weekday AND the time is between 9 and 17 (inclusive), also print “Don’t forget your work/study tasks!”
  4. Use a for-in loop to print a reminder for 3 important tasks, like “Task 1: Check emails”, “Task 2: Attend meeting”, “Task 3: Plan tomorrow”.

Hint: You’ll need to combine if-else if-else, logical operators (&&, ||), and a for-in loop. Think about how to represent the tasks.

What to Observe/Learn: How different control flow statements work together to create more complex logic. Pay attention to how the conditions are nested or combined.

// Your code here for the Mini-Challenge!
// Try to solve it before looking at any potential solutions.
Click for a hint if you're stuck!

Think about how to represent the tasks for the loop. A simple array of strings for task descriptions would work well. For the time-based suggestions, remember to use logical AND (&&) for combining hour conditions (e.g., hour >= 9 && hour <= 12). For the weekday-specific reminder, you’ll likely need another if statement inside the relevant time block, checking both the isWeekday boolean and the hour.

Common Pitfalls & Troubleshooting

Even experienced developers encounter these sometimes!

  1. = vs. ==: A classic! Using a single = (assignment) inside an if condition when you meant == (comparison) will lead to a compile-time error in Swift because if conditions must evaluate to a Bool, and an assignment operation does not.

    • if (x = 5)
    • if x == 5
  2. Infinite Loops: Forgetting to update the condition variable in a while or repeat-while loop can cause your program to freeze. Always ensure there’s a mechanism for the loop’s condition to eventually become false.

    • Troubleshooting: If your Playground or app hangs, you likely have an infinite loop. Look for while or repeat-while loops and check their conditions and the code inside them.
  3. Off-by-One Errors in Loops/Ranges: When using ranges like 0..<5 vs. 0...5, or conditions like < vs. <=, it’s easy to include one too many or one too few iterations.

    • Troubleshooting: Use print() statements to check the value of your loop counter (i in for-in) at the beginning and end of the loop’s execution. Carefully review whether you need to include the upper bound or not.
  4. Non-Exhaustive switch Statements: If you switch over an enum or certain other types and don’t cover all possible cases (or provide a default), Swift will issue a compile-time error. This is a safety feature!

    • Troubleshooting: Add a default case to catch any unhandled values, or ensure all enum cases are explicitly listed.

Summary

Phew, that was a lot of powerful concepts! Here’s a quick recap of what we covered:

  • Operators are special symbols that perform operations:
    • Arithmetic: +, -, *, /, % for calculations.
    • Assignment: =, +=, -= etc., for assigning and updating values.
    • Comparison: ==, !=, <, >, <=, >= for checking relationships, returning Bool.
    • Logical: && (AND), || (OR), ! (NOT) for combining or inverting Bool conditions.
    • Range: ... (closed) and ..< (half-open) for defining sequences.
    • Ternary Conditional: condition ? valueIfTrue : valueIfFalse for concise if-else.
  • Conditionals allow your code to make decisions:
    • if executes code if a condition is true.
    • if-else provides an alternative path if the if condition is false.
    • if-else if-else handles multiple sequential conditions.
    • switch provides a clean, exhaustive, and powerful way to match a single value against multiple patterns.
  • Loops enable repetitive execution of code:
    • for-in iterates over sequences (like ranges or collections).
    • while repeats as long as a condition is true (checked before iteration).
    • repeat-while repeats as long as a condition is true (checked after iteration, guaranteeing at least one run).
    • break exits a loop immediately.
    • continue skips the current iteration and moves to the next.

With operators, conditionals, and loops, you now have the fundamental tools to write programs that are dynamic, responsive, and efficient. You can perform calculations, react to different scenarios, and automate repetitive tasks. This is a massive step towards building real-world applications!

What’s Next?

In Chapter 4: Functions, we’ll learn how to organize your code into reusable, named blocks. This will allow you to create modular, maintainable, and scalable applications by encapsulating specific tasks into their own self-contained units. Get ready to write even cleaner and more powerful Swift!

References


This page is AI-assisted and reviewed. It references official documentation and recognized resources where relevant.