Lessons
Variables, constants, and type inference
let vs var, type inference, String interpolation, if/else, for-in, while, switch with pattern matching.
What to look for:
- let = constant (prefer); var = variable — Swift prefers immutability
- Type inference: let name = "Alice" — Swift knows it's a String
- String interpolation: "Hello, \(name)! You are \(age) years old."
- switch is exhaustive and doesn't fall through — no break needed, no default if all cases covered
Optionals: if let, guard let, and ??
Optional type (T?), if let, guard let (early exit), optional chaining (?.), nil coalescing (??), and when to use force-unwrap (!).
Prerequisite: Lesson 1
What to look for:
- String can never be nil; String? may be nil — the ? is part of the type
- guard let: unwrap or return early — the unwrapped value is usable after the guard
- ?. optional chaining: returns nil if any link in the chain is nil (doesn't crash)
- ! force-unwrap crashes on nil — only use when you have a guarantee the value exists
Structs vs classes: value and reference semantics
struct (value type — copied on assignment), class (reference type — shared), mutating methods, Copy-on-Write, and when to choose each.
Prerequisite: Lesson 2
What to look for:
- Assigning a struct makes a copy — mutating one doesn't affect the other
- Assigning a class copies the reference — both point to the same object
- mutating keyword: struct methods that modify self must be marked mutating
- Swift standard library: Array, String, Dictionary are all structs (with CoW optimisation)
Closures and higher-order functions
Closure syntax, trailing closures, capturing values, map/filter/reduce, and shorthand argument names ($0, $1).
Prerequisite: Lesson 3
What to look for:
- Trailing closure: if the last argument is a closure, move it outside the parentheses
- Shorthand: { $0 * 2 } vs { (n: Int) -> Int in return n * 2 } — same thing, shorter
- Closures capture variables by reference — be careful with retain cycles when capturing self
- [weak self] in capture list: breaks retain cycles in closures that reference self
Enums with associated values and pattern matching
Swift enums with associated values, exhaustive switch, if case, Result<T, E>, and using enums for state machines.
Prerequisite: Lesson 4
What to look for:
- Swift enums can carry data: case success(String), case failure(Error)
- switch on enum is exhaustive — compiler warns if a case is missing
- Result<Success, Failure> is the built-in success/failure enum — used everywhere in async APIs
- if case .success(let data) = result — pattern matching without full switch
How to use this track: Each lesson links to the Swift reference pages. Practice at swift.org/swift-online/. Apple's own "The Swift Programming Language" book at docs.swift.org is free and excellent.
Track quiz
4 questions to check your understanding.
What does guard let name = optionalName else { return } do?
What happens when you assign a struct to a new variable?
Why must struct methods that modify self be marked mutating?
What is Result<String, Error> in Swift?