iOS · 13 min
Swift interview questions and answers, as they are scored
Swift interview questions with spoken answers: value and reference types, protocols, generics, memory and errors, and the follow-up each one leads to.
iOS · 18 min read
iOS interview questions for 2026, organised by round: Swift, concurrency, memory, SwiftUI, UIKit, architecture, system design, testing, coding and behavioural.
An iOS loop in 2026 is not one interview. It is a sequence of rounds, and each round asks a different kind of question. A phone screen checks that you know Swift. A concurrency round checks whether you can reason about isolation. A system design round checks whether you can build a whole feature and defend the trade-offs. A behavioural round checks whether people want to work with you.
This page is the map. For each round I give a handful of representative iOS interview questions, a short answer that would pass, and a link to the deeper guide for that area. I have run more than 500 interviews from the hiring side, and the pattern is always the same: candidates prepare definitions, and interviewers score what happens after the definition. So read the short answers as the floor, not the ceiling.
If you want ranked lists instead of a map, there are three: the top 10 iOS interview questions with weak and senior answers, the top 50 grouped by area, and the top 100 for a fast final pass.
Most loops I have sat on follow a similar shape, even when the names of the rounds differ. A typical loop looks like the table below; companies differ in the order, the number of rounds and their length.
| Round | What it checks | Typical length |
|---|---|---|
| Recruiter or phone screen | Swift basics, experience, communication | 30 to 45 minutes |
| Technical deep dive | Swift, concurrency, memory, one framework in depth | 45 to 60 minutes |
| Live coding | Writing working Swift while talking | 45 to 60 minutes |
| iOS system design | Designing a feature or app end to end | 45 to 60 minutes |
| Architecture or code review | Reading code, spotting problems, proposing structure | 45 minutes |
| Behavioural | Ownership, conflict, delivery, influence | 45 minutes |
The questions below follow that order. Junior and mid-level loops lean on the first three rows. Senior and staff loops lean harder on the last three, and the technical interview guide covers how the deep dive round runs minute by minute.
The Swift round opens almost every loop. The questions sound basic, and that is the trap: the interviewer is listening for whether you know why the language works the way it does.
What is scored: value semantics versus reference semantics, and when each one matters.
Answer: A struct is a value type, so assigning or passing it makes an independent copy, and mutation of one copy never affects another. A class is a reference type, so two variables can point at the same instance, it supports inheritance, and ARC manages its lifetime. Models start as structs in my code; a class earns its place when several owners must see one instance, or when something must outlive the scope that made it. The precise point interviewers wait for: a struct is not thread safe just because it is a value, since a struct that stores a class reference still shares that object.
What is scored: whether you treat nil as a real state rather than an inconvenience.
Answer: An optional is an enum with two cases, some(Wrapped) and none, so the compiler forces you to handle absence. I unwrap with if let, guard let, ?? or optional chaining. A force unwrap is acceptable only where nil would be a programmer error you want to crash on, such as a resource bundled with the app, and even then I prefer a guard with a clear fatalError message.
What is scored: understanding generics and existentials, not just syntax.
Answer: An associated type lets the protocol talk about a type that each conformer chooses, like Element in Collection. The cost is that you cannot use it as a plain existential without any, and calling requirements that mention the associated type through any has limits. When the concrete type is known at the call site, I use generics or some to keep static dispatch and full type information.
The deeper Swift questions, including copy on write, some versus any, and result builders, are in the Swift interview questions guide. If you only have an evening, read that one before anything else on this page.
Since Swift 6 made strict concurrency checking the default in the new language mode, this round has become the one that separates mid-level from senior most quickly.
What is scored: data races versus logical races.
Answer: An actor protects its mutable state by allowing only one task at a time to run code isolated to it, which removes data races on that state. It does not remove every race: at each await inside an actor method, other work can run on the actor, so state you read before the suspension may have changed after it. I re-check assumptions after every await. The same care applies to Swift 6: strict checking finds many unsafe crossings while compiling, yet logical races, deadlocks and cancellation bugs all survive it, and saying where the guarantee ends scores better than sounding impressed by it.
What is scored: whether you can explain the compiler’s rule, not recite it.
Answer: Sendable is the compiler’s label for a type that may cross from one isolation domain to another. Non-public structs and enums built from sendable parts qualify implicitly (public ones must declare it), actors are always sendable, and a final class qualifies only if its stored properties are immutable and sendable. Marking something @unchecked Sendable moves the proof from the compiler to me, so I only do it with a lock or other synchronization I can point to.
Task and Task.detached?”What is scored: understanding inherited context.
Answer: Task { } inherits the current actor, priority and task-local values, so a task created on the main actor runs its synchronous parts there. Task.detached inherits none of that. I almost never need detached, because dropping isolation, priority and task-local values at once is rarely what anyone meant. If I want work off the main actor, a separate actor or a function marked @concurrent states the intent more clearly. Under the approachable concurrency settings that new Xcode 26 projects turn on, a plain nonisolated async function stays on whichever actor called it, so @concurrent is the explicit way to ask for the hop.
Concurrency questions carry the most weight in senior loops, and the senior iOS interview questions guide walks through the follow-ups interviewers use to push on them.
Memory questions are short and unforgiving. Most candidates know the word “retain cycle”. Fewer can find one in code on a shared screen.
What is scored: a working mental model of reference counts.
Answer: The compiler adds retain and release operations for me, and an instance is freed when its strong reference count reaches zero. A cycle forms when a pair of objects keep strong pointers at one another, directly or through a closure that captures self, so neither count reaches zero. I break it with weak or unowned on the side that does not own the other.
unowned instead of weak?”What is scored: reasoning about lifetimes, not a rule of thumb.
Answer: A weak reference turns into nil once its target is freed, which makes it the safe default. unowned is not optional, and touching it after the target is freed traps, so I keep it for cases where the target provably lives longer, like a back pointer from a child object its parent creates and destroys. When I am not sure, I pick weak.
A good habit for this round is to say how you would verify the fix: the memory graph debugger in Xcode, or a deinit log in a debug build. That one sentence turns a textbook answer into an engineer’s answer.
Most teams in 2026 ship both frameworks, so expect questions on each and at least one about how they meet.
@State, @Binding and @Observable?”What is scored: who owns the data.
Answer: @State is storage owned by the view, kept alive by SwiftUI across view updates. @Binding is a reference to state owned by someone else, so the child can read and write it without owning it. @Observable is a macro for a model class where SwiftUI records which properties each body touched, so a change to an unread property does not redraw that view. It usually means fewer redraws than ObservableObject, not only the changed property: a parent body running again, a new identity or an environment update will still invalidate a view. I hold an observable model in @State in the view that creates it.
What is scored: understanding identity and invalidation.
Answer: SwiftUI calls body whenever a dependency the view read changes, and view structs are cheap values that get recreated often. The cost comes from expensive work inside body, unstable identity in lists, or a large model where one change invalidates many views. I keep body pure, give ForEach stable identifiers, and split views so each reads only what it needs.
What is scored: knowing where work belongs.
Answer: loadView creates the view, viewDidLoad runs once for one-time setup, viewWillAppear and viewDidAppear run on every appearance, and the disappear pair mirrors them. Layout-dependent code goes in viewDidLayoutSubviews or in Auto Layout, not in viewDidLoad, because bounds are not final there yet. viewIsAppearing, available back to iOS 13 when built with the iOS 17 SDK, is a good place for appearance work that needs the trait collection and geometry to be accurate.
For the full set, see the SwiftUI interview questions and the UIKit interview questions. The UIKit guide also covers cell reuse and diffable data sources, which still come up in almost every loop that touches a mature codebase.
The architecture round rarely asks you to name a pattern. It asks you to justify one.
What is scored: judgement tied to team and product constraints.
Answer: I choose by the problem the team has. MVVM with observable models fits most SwiftUI apps and is easy to hire for. TCA gives strict, testable state flow at the cost of a learning curve and a dependency. VIPER suits large UIKit codebases with many teams but adds a lot of ceremony. Whatever I pick, the rules I care about are the same: one owner for each piece of state, side effects behind protocols, and navigation that can be tested.
What is scored: testability without a framework habit.
Answer: I inject dependencies through initializers by default, as protocols or plain structs of closures, so tests can pass fakes. For SwiftUI I use the environment for app-wide services. I avoid singletons reached from deep inside views, because they hide coupling and make tests order-dependent.
The iOS architecture interview questions guide goes further into modularisation and navigation, which is where senior candidates usually get pushed.
The iOS system design round asks you to design a feature, not a data centre. Think feeds, chat, offline sync, image loading.
What is scored: layering, cancellation and memory pressure.
Answer: I would build a memory cache with a cost limit, a disk cache keyed by URL, and a loader that deduplicates in-flight requests for the same URL. Each cell cancels its load when it is reused or disappears. I would downsample images to the display size at decode time, off the main thread, before caching them in memory. For the memory layer I would use NSCache but not describe it as an LRU cache: it evicts on its own under memory pressure, with no strict ordering promise.
What is scored: source of truth and conflict handling.
Answer: The local store becomes the source of truth and the UI reads only from it. Writes go to the store first and into an outbox queue, which syncs when the network returns, with retries and idempotency keys. I would state the conflict rule up front, such as a per-field merge, and avoid whole-record last write wins for user-written text because it silently loses edits. I would show pending state in the UI so the user is never lied to. Connectivity checks like NWPathMonitor are only a hint, so the outbox has to cope with requests that fail even when the path looks good.
Both of these have full walkthroughs in the iOS system design interview guide, including how to spend the first five minutes on requirements before drawing anything.
Testing questions are often folded into other rounds. When I ask one, I am checking whether testability shaped the design or was bolted on after.
What is scored: tests that give the same result every run.
Answer: With Swift Testing or XCTest I write async test functions and await the code directly. I inject clocks, network clients and schedulers so the test controls time and results, instead of sleeping, because any test tied to the wall clock will eventually flake. For code that emits several values I collect them and assert on the sequence, and I test cancellation and the rejection of stale results, not only the happy path.
What is scored: a sense of cost per test.
Answer: In the view model I test state transitions: loading, success, empty, error, and retry, using fake dependencies. UI tests are slow and brittle, so I keep them for a few critical flows like sign in and checkout. Snapshot tests cover layout regressions in between.
A candidate who says “I would add tests later” loses more points here than one who admits a gap and explains how they would close it.
Live coding in an iOS loop is usually a small, practical task in Swift: parse data, build a small component, fix a bug. The iOS coding interview guide covers the format in detail.
What is scored: working code, plus cancellation.
Answer: In Swift concurrency I keep a reference to the current search task. On each keystroke I cancel it and start a new task that sleeps for the debounce interval, checks for cancellation, then runs the search. In SwiftUI, .task(id: query) gives the same behaviour because it cancels and restarts the task whenever the query changes.
.task(id: query) {
try? await Task.sleep(for: .milliseconds(300))
guard !Task.isCancelled else { return }
await model.search(query)
}What gets scored in this round is as much the talking as the typing. Say what you are about to write, write it, run it, then say what you would change with more time.
The behavioural round is scored as seriously as the technical ones, and at senior level it often decides the outcome.
What is scored: ownership, clarity and what changed afterwards.
Answer: Pick a real incident. Say what users saw, how you found out, what you did in the first hour, the root cause, and the change that stops it from happening again. The last part matters most: a process or code change, not “we were more careful”.
What is scored: whether you can disagree and still move forward.
Answer: Describe the two positions fairly, how you tested them with data or a small prototype, what was decided, and what you learned if you were wrong. Interviewers listen for respect toward the other person. Blame is the fastest way to fail this question.
Senior and staff behavioural questions add influence across teams and mentoring; the senior iOS guide covers those follow-ups.
@MainActor written on every type.@concurrent attribute marks a function that should run concurrently, which makes it visible in the code when work leaves the actor.These are the references I would check an answer against. When an interviewer and a blog post disagree, the official docs usually settle it.
Pick the round you feel least ready for and spend your next hour there. Reading answers builds recognition; saying them aloud, with someone pushing back, is what builds the answer you will give.

iOS · 13 min
Swift interview questions with spoken answers: value and reference types, protocols, generics, memory and errors, and the follow-up each one leads to.

iOS · 13 min
SwiftUI interview questions on identity, state ownership, Observation and performance, each with the answer that scores, the trap and the follow-up.

iOS · 16 min
Twelve senior iOS interview questions for 2026: what each scores, a weak and a senior answer, and the follow-up on Swift 6 concurrency, SwiftUI, architecture.