A seven-week SwiftUI course

SwiftUI Quest

✦

For an experienced UIKit engineer who last wrote Swift around 2016. 49 days of work: seven weeks at one a day, or at your own pace. The goal: pass a senior iOS interview.

49 days of work
Pace54 lessons in 49 days of work. Most days have one lesson and seven have two; the last two days are practice interviews. A lesson takes about an hour to ninety minutes.
ToolsXcode 27, iOS 27, Swift 6.4
Starting pointEighteen years of iOS with UIKit. Swift last used around 2016.
ProjectsDays 1–3: three small projects you set up from scratch in Xcode. Together they make TinyUI, a miniature SwiftUI you write yourself. After that: Trips, one app that grows with each part.
Days done
0 of 49
Interview problems solved
0 of 11

How this works

  1. Press Start the course and choose your start and finish dates. The 49 days of work are laid out between them, and every page then shows your own dates.
  2. Every day has its own page. Open today’s from the calendar below.
  3. Work through that page in Xcode, typing the code yourself. Days 1–3 are step-by-step tutorials that build something, starting each time from File ▸ New ▸ Project…; later days have lesson notes until their tutorials are written.
  4. Go through the flash cards at the end of the page until you can answer each one before you tap it.
  5. On the last day of each part, try the interview problem before you look at its answer.
  6. Mark the day done.

Keep these open

Part 1 · Days 1–4 · Lessons 1–5
✦

Modern Swift: what changed since 2016

✦

Swift changed a great deal after Swift 3. Every piece of SwiftUI syntax that looks unusual is really a language feature added since then. This part covers those features on their own, before any SwiftUI.

You buildTinyUI — a miniature SwiftUI that prints to the console, written by you in about 150 lines.

You can explainWhat some View promises the compiler; what $value really is; what @Observable generates.

above the line: the Swift release; below: the SwiftUI syntax it made possible 20162019 202120232026 WHERE YOU LEFT OFF · SWIFT 3 SWIFT 5.1 property wrappers · opaque types · result builders SWIFT 5.9 macros SWIFT 4 · CODABLE · KEY PATHS SWIFT 5.5 · ASYNC/AWAIT · ACTORS SWIFT 6 → 6.4 · STRICT CONCURRENCY → some View · @State · the body { } block → @Observable · #Preview → .task { await … } → @MainActor by default · @concurrent
Swift releases since 2016, and the SwiftUI syntax each one made possible
Day 1

Build your own property wrappers

Lesson 1: Property wrappers. How @Something var works, and what the $ prefix really is.

Build-along tutorial →
Day 2

Build the pieces of a tiny UI framework

Lesson 2: Opaque types and existentials: some vs any. Why every SwiftUI view returns some View, and what that promises the compiler.

Build-along tutorial →
Day 3

Give TinyUI the syntax of SwiftUI

Lesson 3: Result builders. How a block of views with no commas and no return becomes a single value.

Build-along tutorial →
Day 4

Macros

What @Observable and #Preview actually do, and how to read the code they generate.

Everything else that changed since 2016

The rest of modern Swift you will be expected to use without thinking.

Then the interview problem for this part: A helper that will not compile

Lesson notes →
Part 2 · Days 5–7 · Lessons 6–8
✦

Getting started with SwiftUI

✦

How a SwiftUI app starts, how a view works, and the preview workflow that replaces build-and-run.

You buildYour first SwiftUI project, developed entirely in previews.

You can explainWhy a view is a struct; when body runs; what a scene is.

Day 5

Xcode previews

Seeing a view update live as you type, without launching the app.

Lesson notes →
Day 6

App structure: @main, App, Scene, WindowGroup

What replaces AppDelegate and SceneDelegate, and what a scene is.

Lesson notes →
Day 7

How a view works: body and some View

A view is a description, not an object on screen — and what follows from that.

Then the interview problem for this part: The analytics event that fired forty times

Lesson notes →
Part 3 · Days 8–11 · Lessons 9–13
✦

Views and layout

✦

Showing content and arranging it. Stacks and modifiers replace most of what you used Auto Layout for.

You buildOne UIKit screen you know well, rebuilt in SwiftUI.

You can explainThe three steps of layout; why the order of modifiers matters.

Day 8

Text, images, and SF Symbols

Showing text, pictures, and icons, and making images fit their frames.

Lesson notes →
Day 9

Stacks, spacers, and alignment

Arranging views in rows, columns, and layers — the replacement for most Auto Layout.

Lesson notes →
Day 10

How layout works: frames and sizing

The three-step negotiation between a parent and its child that decides every size.

Lesson notes →
Day 11

View modifiers, and why their order matters

Each modifier wraps the view before it, so order changes the result.

Grids and custom layouts

Tables, scrolling grids, and writing your own container when neither fits.

Then the interview problem for this part: An infinite photo carousel

Lesson notes →
Part 4 · Days 12–15 · Lessons 14–17
✦

State and data flow

✦

Where data lives, who is allowed to change it, and how SwiftUI knows which views to update. This is the part interviews probe hardest.

You buildThe Trips app, version 1: a model, a screen, and editing.

You can explain@State versus @Binding versus @Observable versus the environment; what view identity is.

Day 12

@State and @Binding

Who owns a piece of data, and how another view gets to change it.

Lesson notes →
Day 13

@Observable models

Data shared across screens, and how SwiftUI knows which views to update.

Lesson notes →
Day 14

The environment

Passing values down the view tree without threading them through every initializer.

Lesson notes →
Day 15

View identity and lifetime

How SwiftUI decides whether a view is "the same view" — the idea behind most surprises.

Then the interview problem for this part: The counter that resets

Lesson notes →
Part 5 · Days 16–19 · Lessons 18–22
✦

Lists and navigation

✦

Scrolling lists, moving between screens, and presenting sheets — all of it driven by state.

You buildTrips: a list with detail screens, an editing sheet, and search.

You can explainWhy navigation is data; why every row needs a stable id.

Day 16

List and ForEach

Scrolling rows of data, and why every row needs a stable identity.

Lesson notes →
Day 17

NavigationStack and programmatic navigation

Pushing screens, and treating the navigation stack as plain data.

Lesson notes →
Day 18

Split views and adapting to screen size

One layout that works on iPhone, iPad, and Mac — and at any window size.

Sheets, alerts, and popovers

Presenting a screen by changing state, rather than by calling present.

Lesson notes →
Day 19

Toolbars, menus, and search

Bar buttons, pull-down menus, and a search field that filters your data.

Then the interview problem for this part: A deep link into a navigation stack

Lesson notes →
Part 6 · Days 20–24 · Lessons 23–27
✦

Drawing and animation

✦

Custom shapes, and animation — which in SwiftUI means changing state and letting the framework animate the difference.

You buildTrips: a custom-drawn header, a chart, and one animated transition.

You can explainThe difference between an animation and a transition.

Day 20

Shapes and paths

Drawing with built-in shapes and with paths of your own.

Lesson notes →
Day 21

Gradients, materials, and shadows

Colour that changes across a view, translucent backgrounds, and depth.

Lesson notes →
Day 22

Canvas

Drawing thousands of things quickly, when one view per thing would be too slow.

Lesson notes →
Day 23

Animation basics

You change state; SwiftUI animates the difference.

Lesson notes →
Day 24

Transitions and matched geometry

How views appear and disappear, and making one view seem to become another.

Then the interview problem for this part: The card that fades instead of growing

Lesson notes →
Part 7 · Days 25–27 · Lessons 28–31
✦

Input and interaction

✦

Controls, text entry, gestures, and drag and drop.

You buildTrips: a settings form, and cards you can drag.

You can explainHow a control reports a change without target–action or a delegate.

Day 25

Controls and forms

Buttons, toggles, pickers, and the standard settings-screen layout.

Text input and focus

Text fields, keyboards, and moving the cursor from field to field in code.

Lesson notes →
Day 26

Gestures

Taps, drags, pinches — and state that resets itself when the finger lifts.

Lesson notes →
Day 27

Drag and drop, and haptics

Moving data between views and apps, and feedback the user can feel.

Then the interview problem for this part: Testing a debounced search

Lesson notes →
Part 8 · Days 28–31 · Lessons 32–35
✦

Data, persistence, and networking

✦

Decoding JSON, loading from the network, and saving to disk.

You buildTrips: saved with SwiftData and loaded from a JSON API, with loading and error states.

You can explainWhat .task ties work to; why loading state should be one enum.

Day 28

Codable and JSON

Turning JSON into your own types, and reading the error when it fails.

Lesson notes →
Day 29

Loading data with async/await

Fetching from the network in a view, with honest loading and error states.

Lesson notes →
Day 30

SwiftData

Saving your model objects to disk and showing them in a view.

Lesson notes →
Day 31

AppStorage and SceneStorage

Remembering small things: user preferences and where the user left off.

Then the interview problem for this part: The take-home, in miniature

Lesson notes →
Part 9 · Days 32–38 · Lessons 36–43
✦

Swift concurrency

✦

async/await, actors, and Swift 6's data-race checking, which together replace GCD. This is as large a change as SwiftUI itself, and interviews for senior roles lean on it.

You buildTrips: networking rebuilt with structured concurrency, an actor-based cache, and tests that never wait on real time.

You can explainActor isolation and reentrancy; what Sendable means; how to migrate a codebase to Swift 6.

Day 32

Structured concurrency

Running work in parallel with a clear owner, automatic cancellation, and errors that surface.

Actors and @MainActor

Protecting shared data without locks, and keeping UI work on the main thread.

Lesson notes →
Day 33

Sendable and Swift 6 strict concurrency

How the compiler rules out data races, and how to migrate an older codebase.

Lesson notes →
Day 34

AsyncSequence and AsyncStream

Values that arrive over time, and wrapping old callback APIs so you can loop over them.

Lesson notes →
Day 35

Combine: reading legacy code

Where Combine stands in 2026, and how to migrate away from it.

Lesson notes →
Day 36

Concurrency in SwiftUI

Starting async work from a view so that it is cancelled when the view goes away.

Lesson notes →
Day 37

Testing async code

Writing tests for async functions, and what makes them possible.

Lesson notes →
Day 38

Controlling time in tests

Testing a debounce or a timeout without making the test wait.

Then the interview problem for this part: Two downloads for one image

Lesson notes →
Part 10 · Days 39–41 · Lessons 44–47
✦

Architecture, testing, and performance

✦

Keeping a growing app readable, testable, and fast.

You buildTrips: split into small views, with previews for every state, and a performance pass.

You can explainHow you would test a SwiftUI view; what causes a view to re-render.

Day 39

Breaking a screen into small views

Why small, named views are easier to read and faster to update.

Passing dependencies

Giving a view what it needs so that it can be previewed and tested.

Lesson notes →
Day 40

Previews and tests

What to check with a preview, what to check with a test, and how to "test a view".

Lesson notes →
Day 41

Performance

Why a view re-renders, and how to find the ones that re-render too often.

Then the interview problem for this part: Testing code that depends on today's date

Lesson notes →
Part 11 · Days 42–47 · Lessons 48–54
✦

Platform features and shipping

✦

Dark mode, Liquid Glass, accessibility, localization, widgets, shipping — and using SwiftUI inside a UIKit app.

You buildTrips: polished, uploaded to TestFlight, and one screen hosted inside a UIKit app.

You can explainHow to adopt SwiftUI gradually in an existing UIKit codebase.

Day 42

Dark mode and theming

Colours that adapt to light and dark mode without extra code.

Lesson notes →
Day 43

Liquid Glass

The design language introduced in iOS 26, and how your own controls adopt it.

Lesson notes →
Day 44

Accessibility

VoiceOver, Dynamic Type, and what you have to add yourself.

Lesson notes →
Day 45

Localization

Translating an app, handling plurals, and layouts that survive longer text.

Lesson notes →
Day 46

Widgets, App Intents, and Foundation Models

Your app outside your app: the Home Screen, Siri, and the on-device language model.

Shipping to the App Store

Archive, upload, test with TestFlight, and submit for review.

Lesson notes →
Day 47

Using SwiftUI with UIKit

Mixing the two frameworks — the way most real apps adopt SwiftUI.

Then the interview problem for this part: Wrapping a UIKit view for SwiftUI

Lesson notes →
Days 48–49
✦

Mock interviews

✦

Three timed practice interviews, and a review of whatever is not yet solid.

Day 48

Mock interviews 1 and 2

Timed practice interviews, then a review of everything not yet solid.

Practice →
Day 49

Mock interview 3, and review

Timed practice interviews, then a review of everything not yet solid.

Practice →

54 lessons in 11 parts, with 11 interview problems. Current to Xcode 27, iOS 27 and Swift 6.4.
Every piece of code on these pages was compiled before it was published, and every screenshot was taken from a running app.