Basic Control Flow: Booleans, Decisions & Loops

Swift Chapter 5 of the Ultimate Swift Series 30 min read April 10, 2026 Beginner

In This Article

  1. Booleans: True and False
  2. Comparison Operators
  3. Boolean Logic: AND, OR, NOT
  4. Comparing Strings
  5. Making Decisions With if
  6. Chaining Conditions With else-if
  7. Short-Circuit Evaluation
  8. Variable Scope
  9. The Ternary Operator
  10. While Loops
  11. Repeat-While Loops
  12. Breaking Out of Loops
  13. Exercises
  14. Key Points

So far, your code has been linear — it runs from top to bottom, every line, every time. Real programs need to make decisions: do one thing when a user taps "Buy", something else when they tap "Cancel". They also need to repeat work: process every item in a shopping cart, retry a failed network request, animate a loading spinner.

This is control flow — the mechanisms that control which code runs and how many times. This chapter covers the foundations: Booleans for representing truth, comparison operators for testing conditions, if statements for making decisions, and while loops for repeating work.

Booleans: True and False

Swift has a type called Bool (short for Boolean, named after mathematician George Boole) that can only hold one of two values: true or false.

let isLoggedIn = true let hasPermission = false

Booleans are the foundation of every decision your code makes. Every if statement, every loop condition, every toggle in your UI — all built on Booleans.

You can flip a Boolean's value with the toggle() method:

var lightIsOn = true lightIsOn.toggle() // false lightIsOn.toggle() // true again

Comparison Operators

You rarely create Booleans by writing true or false directly. Instead, they come from comparisons:

let isEqual = (5 == 5) // true (equal to) let isNotEqual = (5 != 3) // true (not equal to) let isGreater = (10 > 7) // true (greater than) let isLess = (3 < 8) // true (less than) let isGTE = (5 >= 5) // true (greater than or equal) let isLTE = (4 <= 3) // false (less than or equal)

Each comparison produces a Bool. The ! prefix operator (the NOT operator) flips any Boolean:

let isNotFive = !(5 == 5) // false (5 IS 5, but ! flips it)

Boolean Logic: AND, OR, NOT

Single comparisons are useful, but real decisions often depend on multiple conditions. Swift provides two operators for combining Booleans:

AND (&&) — both must be true

let hasTicket = true let hasID = true let canEnter = hasTicket && hasID // true (both are true)

If either input is false, the result is false. You need a ticket AND an ID to enter.

OR (||) — at least one must be true

let isWeekend = false let isHoliday = true let dayOff = isWeekend || isHoliday // true (holiday is true)

Only if both inputs are false does the result become false.

Combining conditions

You can chain these together. Use parentheses to make the logic clear:

let age = 25 let hasLicense = true // Can rent a car: must be 21+ AND have a license let canRent = (age >= 21) && hasLicense // true // Complex: (false AND true) OR true = true let complex = (1 > 2 && 3 > 2) || 5 > 1 // true

Comparing Strings

You can compare strings with the same operators you use for numbers:

let answer = "cat" let isCorrect = (answer == "cat") // true let isBefore = ("apple" < "banana") // true (alphabetical order)

The < and > operators compare strings alphabetically. This is useful for sorting and searching.

Making Decisions With if

The if statement is how your program makes decisions. If a condition is true, run this code. Otherwise, skip it.

let temperature = 35 if temperature > 30 { print("It's hot outside!") }

The code inside the braces only runs if temperature > 30 is true. If it's false, Swift skips it entirely.

Adding else

You often want to do something different when the condition is false:

let animal = "Zebra" if animal == "Cat" || animal == "Dog" { print("It's a house pet.") } else { print("It's not a house pet.") } // Prints: "It's not a house pet."

Chaining Conditions With else-if

When you have multiple possible outcomes, chain conditions with else if:

let hour = 14 var greeting: String if hour < 6 { greeting = "Early morning" } else if hour < 12 { greeting = "Good morning" } else if hour < 17 { greeting = "Good afternoon" } else if hour < 21 { greeting = "Good evening" } else { greeting = "Good night" } print(greeting) // "Good afternoon"

Swift checks each condition from top to bottom and runs the first one that's true. Once a match is found, it skips all remaining conditions. This means order matters — put more specific conditions first.

Order matters

If you checked hour < 21 before hour < 17, the value 14 would match "Good evening" instead of "Good afternoon". Always order your conditions from most specific to least specific.

Short-Circuit Evaluation

Swift is smart about evaluating Boolean expressions. With &&, if the first condition is false, Swift doesn't bother checking the second — the result is already false. With ||, if the first condition is true, Swift skips the second — the result is already true.

// Swift never checks the second condition here: if 1 > 2 && someExpensiveCheck() { // Won't run — first condition is false }

This is called short-circuit evaluation. It's not just an optimization — it lets you write safe conditions where the second check depends on the first being true.

Variable Scope

Every pair of braces {} creates a new scope. Variables and constants declared inside a scope only exist within that scope:

var total = 0 if true { let bonus = 100 total += bonus // OK — total is from the parent scope } print(total) // OK — 100 print(bonus) // ERROR — bonus doesn't exist here

The constant bonus was created inside the if block's scope and dies when that scope ends. But code inside a scope can access variables from its parent scope — that's how total gets modified.

This scoping rule prevents variables from leaking into places they shouldn't be and keeps your code clean.

The Ternary Operator

For simple "if this, then that, otherwise the other thing" decisions, Swift has a one-line shorthand called the ternary conditional operator:

// condition ? valueIfTrue : valueIfFalse let a = 5, b = 10 let smaller = a < b ? a : b // 5 let larger = a > b ? a : b // 10

This replaces a 5-line if/else block with a single expression. Use it when the logic is simple and fits on one line. For anything more complex, stick with if/else — readability always wins.

Built-in min and max

Finding the smaller or larger of two values is so common that Swift provides min(a, b) and max(a, b) functions. Use them instead of writing your own ternary for this purpose.

While Loops

A while loop repeats a block of code as long as a condition remains true:

var count = 1 while count <= 5 { print("Count is \(count)") count += 1 } // Prints: Count is 1, Count is 2, ... Count is 5

The loop checks the condition before each iteration. If the condition is false from the start, the body never runs.

Watch for infinite loops

If the condition never becomes false, the loop runs forever. Always make sure something inside the loop changes the condition — like incrementing a counter or modifying the value being tested.

Repeat-While Loops

A repeat-while loop is similar, but it checks the condition after each iteration. This guarantees the body runs at least once:

var roll = 0 repeat { roll = Int.random(in: 1...6) print("Rolled a \(roll)") } while roll != 6 print("Finally rolled a 6!")

This keeps rolling a die until you get a 6. Because it's repeat-while, you always roll at least once — even if the first roll is a 6.

When to use which

Breaking Out of Loops

Sometimes you need to exit a loop early. The break statement immediately stops the loop:

var sum = 1 while true { sum = sum + (sum + 1) if sum >= 1000 { break } } print(sum) // 1023

This pattern — a while true loop with a break condition inside — is useful when the exit condition is complex or appears in the middle of the loop body rather than at the top or bottom.

Exercises

Try These in Your Playground

  1. Create a constant myAge set to your age. Use an if statement to print "Teenager" if the age is between 13 and 19 (inclusive), or "Not a teenager" otherwise.
  2. Rewrite exercise 1 using the ternary operator to set a constant status to either "Teenager" or "Not a teenager", then print it.
  3. Create a while loop that counts from 0 to 9, printing each number.
  4. Create a repeat-while loop that simulates rolling a die (Int.random(in: 1...6)) until you roll a 1. Count and print how many rolls it took.
  5. Evaluate these Boolean expressions by hand, then verify in a playground:
    true && true
    false || false
    (true && 1 != 2) || (4 > 3 && 100 < 1)
    ((10 / 2) > 3) && ((10 % 2) == 0)
  6. Challenge: Write a program that calculates the nth Fibonacci number using a while loop. The sequence starts 1, 1, 2, 3, 5, 8, 13...

Key Points

What You Learned

In the next chapter, we'll cover Advanced Control Flowfor-in loops for iterating over ranges and collections, switch statements for powerful pattern matching, and the continue keyword.

Watch the video lessons

Our Swift Fundamentals course covers control flow, Boolean logic, switch statements, and real-world challenges in 96 video lessons.

Watch Swift Videos