For an experienced UIKit engineer who last wrote Swift around 2016. 57 lessons: about eleven weeks at one each weekday, or at your own pace. The goal: pass a senior iOS interview.
| Pace | 57 lessons, on weekdays only. At one each weekday the course takes about eleven weeks; a shorter plan puts two on some weekdays, and a longer one leaves some free. The last two lessons are practice interviews. A lesson takes from 45 minutes to two hours. |
| Tools | Xcode 27, iOS 27, Swift 6.4 |
| Starting point | Eighteen years of iOS with UIKit. Swift last used around 2016. |
| Projects | Lesson 1: a project made from scratch in Xcode — how it is set up and configured, and what an app is made of. Lessons 2–4: three small projects, each starting from a little app you download. They end in TinyUI, a miniature SwiftUI you write yourself. From lesson 5: Trips, one app that grows with the course — and, in the lessons that try one thing on its own, a small project of their own. |
One subject each, all the way down. Come back to them from any lesson; the lessons that bear on one point to it.
await, in fullFrom one await to a loop, a stream, and an actor of your ownOpen the guide →
Guide · BindingsBinding, @Binding and @BindableFrom one Binding you make by hand, up to the two property wrappers that write it for youOpen the guide →
Guide · ForEachForEach, in fullWhat it keeps, when it makes its rows, and how it tells them apartOpen the guide →
Guide · Key pathsKey paths, in fullEvery kind, every step a path can take, and what the compiler makes of oneOpen the guide →
Guide · @Observable@Observable, in fullHow one plain read in a body signs the view up to be told when the property changesOpen the guide →
Guide · OwnershipOwnership, in full~Copyable, borrowing, consuming and consume, and what the compiler does underneathOpen the guide →
Guide · Result buildersResult builders, in fullEvery method a builder can have, and what SwiftUI's own builder leaves outOpen the guide →
Guide · Retain cyclesRetain cycles in SwiftUIWhen an @Observable model is never freed, and when it is — a screen that only names its model never traps it; the model it owns canOpen the guide →
All nineThe guides, in fullWhat each one covers, section by section, and the lessons it comes from.See them all →
Before any Swift: making an app in Xcode 27 the way an interview expects you to, from a new project to a passing unit test — and a first look at what an app is made of.
A new project in Xcode, and what an app is made of. Making an app the way an interview expects: every option of a new project, its settings and scheme, a unit test that runs — and the parts that replaced the app delegate.
Peek, an app made from scratch with its tests, that shows its own parts: what its bundle says, what its scene is doing, and which actor runs its code.
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.
Property wrappers. How @Something var works, and what the $ prefix really is.
Opaque types and existentials: some vs any. Why every SwiftUI view returns some View, and what that promises the compiler.
Result builders. How a block of views with no commas and no return becomes a single value.
Then the interview problem for this part: A helper that will not compile
How a SwiftUI app starts, how a view works, and the preview workflow that replaces build-and-run.
Xcode previews. Seeing a view update live as you type, without launching the app.
App structure: @main, App, Scene, WindowGroup. What replaces AppDelegate and SceneDelegate, and what a scene is.
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
Showing content and arranging it. Stacks and modifiers replace most of what you used Auto Layout for.
Text, images, and SF Symbols. Showing text, pictures, and icons, and making images fit their frames.
Stacks, spacers, and alignment. Arranging views in rows, columns, and layers — the replacement for most Auto Layout.
How layout works: frames and sizing. The three-step negotiation between a parent and its child that decides every size.
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
The rest of the language under SwiftUI, now that you have built screens that use it. First TinyUI comes back, with a file of 2016 Swift to bring up to date and a macro to read. Then four features, a lesson each: key paths, which name a property; Codable, which turns your types into JSON and back; async/await, which replaces completion handlers; and Observation, which is how a screen hears that a model changed. Part 6 needs all of them.
Macros. What @Observable and #Preview actually do, and how to read the code they generate.
Everything else that changed since 2016. The smaller changes to modern Swift you will be expected to use without thinking — and where the four big ones are taught.
Key paths. A property as a value: what \.city is, what the object behind it holds, and where SwiftUI hands you one.
Codable: what the compiler writes. How a struct becomes JSON and back, which code the compiler writes for you, and how to take over when the JSON does not match.
async and awaitasync and await. A function that waits, a caller that waits for it, and where that waiting happens: the first lesson of concurrency.
Observation: how @Observable works. What a model has to do for a screen to hear that it changed — written by hand first, and then what the macro writes for you.
Where data lives, who is allowed to change it, and how SwiftUI knows which views to update. This is the part interviews probe hardest.
@State and @Binding. Who owns a piece of data, and how another view gets to change it.
@Observable models. Data shared across screens, and how SwiftUI knows which views to update.
The environment. Passing values down the view tree without threading them through every initializer.
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
Scrolling lists, moving between screens, and presenting sheets — all of it driven by state.
List and ForEach. Scrolling rows of data, and why every row needs a stable identity.
NavigationStack and programmatic navigation. Pushing screens, and treating the navigation stack as plain data.
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.
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
Custom shapes, and animation — which in SwiftUI means changing state and letting the framework animate the difference.
Shapes and paths. Drawing with built-in shapes and with paths of your own.
Gradients, materials, and shadows. Color that changes across a view, translucent backgrounds, and depth.
Canvas. Drawing thousands of things quickly, when one view per thing would be too slow.
Animation basics. You change state; SwiftUI animates the difference.
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
Controls, text entry, gestures, and drag and drop.
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.
Gestures. Taps, drags, pinches — and state that resets itself when the finger lifts.
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
Decoding JSON, loading from the network, and saving to disk.
Codable and JSON. Turning JSON into your own types, and reading the error when it fails.
Loading data with async/await. Fetching from the network in a view, with honest loading and error states.
SwiftData. Saving your model objects to disk and showing them in a view.
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
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.
await really doesTasks, await, and the main actor: what the words mean. What a task is, what await really does, and the one rule for the main actor: waiting is free, computing is not.
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.
Sendable and Swift 6 strict concurrency. How the compiler rules out data races, and how to migrate an older codebase.
AsyncSequence and AsyncStream. Values that arrive over time, built by hand first — an async next() and a while let — then as the AsyncSequence that for await is rewritten into, then as an AsyncStream; wrapping old callback APIs so you can loop over them; then a continuation that can be resumed only once, and the ownership rules (~Copyable, consuming, borrowing) that make it so.
Combine: reading legacy code. Where Combine stands in 2026, and how to migrate away from it.
Concurrency in SwiftUI. Starting async work from a view so that it is cancelled when the view goes away.
Testing in SwiftUI. How tests run, how Swift Testing finds and reports them, and what a unit test can see of a view.
Testing async code. Writing tests for async functions, and what makes them possible.
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
Keeping a growing app readable, testable, and fast.
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.
Previews and tests. What to check with a preview, what to check with a test, and how to "test a view".
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
Dark mode, Liquid Glass, accessibility, localization, widgets, shipping, scenes and the background — and using SwiftUI inside a UIKit app.
Dark mode and theming. Colors that adapt to light and dark mode without extra code.
Liquid Glass. The design language introduced in iOS 26, and how your own controls adopt it.
Accessibility. VoiceOver, Dynamic Type, and what you have to add yourself.
Localization. Translating an app, handling plurals, and layouts that survive longer text.
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.
Scenes: windows, phases and the background. What a scene is, what each phase means, what really happens in the background, and how each window keeps its own state.
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
Three timed practice interviews, and a review of whatever is not yet solid.
Timed practice interviews, then a review of everything not yet solid.
Timed practice interviews, then a review of everything not yet solid.
Single pages to come back to: everything the course teaches on one subject, collected, with a flash card for each piece.
What each piece of syntax really is, written out. 14 expansions, each with a flash card.
57 lessons in 13 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.