iOS · 24 min read

Top 50 iOS interview questions and answers (2026)

The top 50 iOS interview questions for 2026, grouped by area, with what each question scores and a senior answer: Swift, concurrency, SwiftUI, UIKit and more.

Fifty questions is roughly what a full iOS loop can draw from. A single loop asks only some of them. Between the phone screen, the technical deep dive, system design and the behavioural round, most of these topics appear somewhere. I have picked them from what I hear most often across the 500-plus interviews I have run for hiring teams, and grouped them by area so you can find your weak spots quickly.

Each question has two parts: what the interviewer is scoring, and a senior answer. The answers are short on purpose. If you want the weak answer and the follow-up for the highest-frequency ones, start with the top 10 iOS interview questions. If you want a map of the rounds, see the iOS interview questions hub.

How the answers are scored

Every answer below is aimed at the same four things I write down after a question.

What I note What earns it
Signal A detail that only someone who has shipped this would mention
Structure A clear first sentence, then reasons in order
Depth The answer survives a second and third question
Judgement When the constraint changes, the answer changes, and you say why

Use the senior answers as a check on your own, not as a script. The point of a list this long is coverage: find the ten you cannot answer cleanly and spend your time there.

Swift language

1. “What is the practical difference between value and reference types?”

What is scored: semantics before memory layout.

Senior answer: Value types copy on assignment, so each holder has an independent value. Reference types share one instance. I pick value types for data and reference types for shared identity or lifetime management. Value semantics are not thread safety, though: they only reach as deep as the stored properties, so a struct holding a class reference still shares it.

2. “How does copy on write work for Swift collections?”

What is scored: knowing copies are cheap until mutation.

Senior answer: Arrays, dictionaries and strings share their storage buffer between copies. The buffer is duplicated only when one copy is mutated and the buffer is not uniquely referenced, which the standard library checks with isKnownUniquelyReferenced.

3. “When do you write some, and when any?”

What is scored: opaque types versus existentials.

Senior answer: some Protocol means a single concrete type, picked by the implementer and hidden from the caller, with static dispatch. any Protocol is a box that can hold any conforming type, with dynamic dispatch and some limits on associated types. I prefer some unless I truly need a mix of types.

4. “Why use guard over if let?”

What is scored: readability and early exit.

Senior answer: guard handles the failure case first and keeps the happy path unindented, and the unwrapped value stays in scope after it. I use if let when both branches do real work.

5. “What are enums with associated values good for?”

What is scored: modelling state so invalid states cannot exist.

Senior answer: They let one type represent mutually exclusive states with their own data, like loading, loaded([Item]) and failed(Error). The compiler then forces every switch to handle each case, which removes a class of bugs from flag combinations.

6. “How does error handling work in Swift?”

What is scored: throws, typed throws and Result.

Senior answer: Functions marked throws propagate errors that callers handle with do/catch or pass on with try. Swift 6 adds typed throws for cases where the error type is fixed. I use Result mainly at boundaries, like storing an outcome, since async throws covers most flows.

7. “What does @escaping mean on a closure?”

What is scored: lifetime of captured values.

Senior answer: It means the closure can be called after the function returns, so it is stored somewhere. That is where capture lists matter, because an escaping closure that captures self strongly can extend its lifetime or form a cycle.

8. “What are protocol extensions, and what is the static dispatch trap?”

What is scored: understanding dispatch rules.

Senior answer: Extensions give default implementations. If a method exists only in the extension and not in the protocol requirements, calls through the protocol type use the extension version even when the conforming type has its own. Declaring it as a requirement fixes that.

Swift questions often open the loop. Short, exact answers here buy you time and goodwill for the harder rounds; the Swift interview questions guide has the longer versions.

Memory and ARC

9. “How does ARC decide when to free an object?”

What is scored: a clear model.

Senior answer: The compiler inserts retain and release operations. When the strong reference count hits zero, deinit runs and memory is freed. Weak references do not count and are set to nil.

10. “What is a retain cycle, with an example?”

What is scored: spotting it in real code.

Senior answer: Two objects holding each other strongly, most often an object that stores a closure capturing self. Neither count falls to zero, so both leak. One side must be weak or unowned.

11. “weak versus unowned?”

What is scored: lifetime reasoning.

Senior answer: weak is optional and becomes nil safely. unowned assumes the other object outlives this reference and crashes if that is false. I use unowned only with a lifetime guarantee I can state.

12. “How do you find a memory leak?”

What is scored: tools and method.

Senior answer: The Xcode memory graph debugger to see what holds an object, Instruments with the Leaks and Allocations templates for growth over time, and deinit logs in debug builds to confirm screens are released.

13. “Can a struct cause a retain cycle?”

What is scored: precision.

Senior answer: A struct itself is not reference counted. It can hold references to classes or closures, and those can take part in a cycle. The struct is just the container.

Memory questions are small, but a wrong answer here is hard to recover from, because it suggests bugs in whatever you have already shipped.

Concurrency

14. “What does async/await improve over completion handlers?”

What is scored: more than syntax.

Senior answer: Straight-line code, errors that propagate with throws, and structured cancellation. The compiler also checks that every path returns, which completion handlers never guaranteed.

15. “What is structured concurrency?”

What is scored: parent and child task lifetimes.

Senior answer: Child tasks created with async let or a task group cannot outlive their parent scope. Cancellation flows from parent to children, and errors flow up. Unstructured Task { } escapes that tree and needs manual management.

16. “What is actor reentrancy?”

What is scored: logical races.

Senior answer: At each await inside an actor, other calls can run on the actor. State read before the suspension may be stale after it, so I re-check it or hold the in-flight task so later callers reuse it.

17. “What does Sendable require?”

What is scored: the compiler’s rule and its escape hatches.

Senior answer: Values that cross isolation domains must be safe to share: value types of sendable fields (implicit for non-public types), actors, or final classes whose stored properties are let and sendable. @unchecked Sendable is my own promise, backed by a lock I can show.

18. “How does cancellation work in Swift concurrency?”

What is scored: cooperative cancellation.

Senior answer: Cancelling a task only sets a flag. Your code has to look at Task.isCancelled, or call try Task.checkCancellation(), and many system APIs, like Task.sleep and URLSession, throw on cancellation for you.

19. “When would you use a task group instead of async let?”

What is scored: static versus dynamic fan-out.

Senior answer: async let fits a fixed, known number of child tasks. A task group fits a number known only at runtime, like downloading every item in a list, and lets me limit concurrency by adding tasks as others finish.

20. “What is nonisolated for?”

What is scored: opting out of actor isolation.

Senior answer: It marks a member of an actor or main actor type that does not touch isolated state, so callers can use it without await. On its own it never moves work off the main thread: a synchronous nonisolated function runs wherever it is called from, and with the approachable concurrency settings a nonisolated async function also stays on the caller’s actor. To leave the main actor on purpose I mark the function @concurrent.

21. “How would you bridge a callback API into async code?”

What is scored: continuations and their rule.

Senior answer: With withCheckedThrowingContinuation, resuming exactly once. Resuming twice crashes and never resuming leaks the task, so I check every callback path, including errors and cancellation.

Concurrency is where senior loops spend the most time in 2026. The senior iOS interview questions guide covers the follow-ups on actors and isolation in more depth than a list can.

SwiftUI

22. “@State, @Binding, @Environment: when is each right?”

What is scored: ownership.

Senior answer: @State for data this view owns, @Binding for data a parent owns, @Environment for values shared down a subtree like a service or a colour scheme. The question underneath is always who owns it.

23. “How does @Observable change updates compared with ObservableObject?”

What is scored: per-property tracking.

Senior answer: ObservableObject publishes any change to any @Published property, so every observing view updates. @Observable tracks which properties a view’s body read, so changes to other properties do not update it, which usually means fewer redraws. It is not only the changed property, though: a parent body running again, a new identity or an environment update will still invalidate the view.

24. “What is view identity?”

What is scored: state lifetime.

Senior answer: Structural identity comes from position in the tree, explicit identity from id or ForEach identifiers. When identity changes, state resets and tasks restart, which is why stable ids matter in lists.

25. “What is the .task modifier for?”

What is scored: lifecycle-bound async work.

Senior answer: It ties async work to the view: the work begins on appearance and is cancelled on disappearance. Give it an id: and it also restarts on each new value, handy for reloading after the selection moves.

26. “How do you find why a SwiftUI view is slow?”

What is scored: measurement before guessing.

Senior answer: The SwiftUI template in Instruments to see body evaluations and long updates, Self._printChanges() in debug to see what triggered a body, then fixes like splitting views, stable identity and moving work out of body.

27. “How do you do navigation in SwiftUI?”

What is scored: state-driven navigation.

Senior answer: NavigationStack with a path bound to state, so navigation is data I can change from code, restore and use for deep links. Destinations are declared with navigationDestination(for:).

28. “How do you use UIKit inside SwiftUI?”

What is scored: bridging responsibility.

Senior answer: UIViewRepresentable or UIViewControllerRepresentable, with makeUIView, updateUIView and a coordinator for delegates. updateUIView must be cheap and idempotent because it runs on every relevant change.

SwiftUI answers are scored on reasoning about state and identity. For more, see the SwiftUI interview questions guide.

UIKit

29. “Describe the view controller lifecycle.”

What is scored: where work belongs.

Senior answer: loadView, viewDidLoad once, then the appear and disappear pairs on each visit. Layout work goes in viewDidLayoutSubviews or constraints, because bounds are not final in viewDidLoad.

30. “How does cell reuse work, and what bug does it cause?”

What is scored: stale state.

Senior answer: Cells are recycled as they scroll off screen. If an async image load finishes after reuse, it can show the wrong image, so I cancel work in prepareForReuse or check that the cell still represents the same item.

31. “Why use diffable data sources?”

What is scored: consistency of updates.

Senior answer: They apply snapshots and compute the differences for me, which removes the classic crash from inconsistent batch updates. Items need stable, hashable identifiers.

32. “Frames versus Auto Layout?”

What is scored: trade-offs.

Senior answer: Auto Layout adapts to size classes, dynamic type and localization. Manual frames can be faster for very complex cells but require me to handle every size change. I use Auto Layout by default.

33. “What runs on the main thread in UIKit, and why?”

What is scored: thread rules.

Senior answer: All UIKit view and controller work, because UIKit is not thread safe. In modern code that is expressed with @MainActor, which UIKit types already carry.

UIKit still runs most large apps, so these come up even in SwiftUI-first loops. The UIKit interview questions guide has the detail.

Architecture

34. “How do you choose an app architecture?”

What is scored: fit to constraints.

Senior answer: By team size, testing needs and what the codebase already uses. MVVM covers most apps; TCA suits teams that want strict state flow; VIPER suits large UIKit teams. Clear state ownership matters more than the name.

35. “How do you inject dependencies?”

What is scored: testability.

Senior answer: Initializer injection by default, with protocols or closure structs. The SwiftUI environment for app-wide services. No hidden singletons inside views.

36. “How would you modularise a large app?”

What is scored: boundaries and build times.

Senior answer: Swift packages per feature with small public interfaces, shared core modules for networking and design system, and feature modules that do not import each other. It speeds builds and makes ownership clear.

37. “How do you handle navigation in a modular app?”

What is scored: decoupling.

Senior answer: Features expose routes or entry points, and a coordinator or router in the app target composes them, so features never import each other just to navigate.

38. “What makes code easy to review?”

What is scored: team empathy.

Senior answer: Small pull requests with one purpose, clear names, tests that show the intent, and a description that explains why. I would rather review five small changes than one large one.

Architecture questions reward specifics from your own work. The iOS architecture interview questions guide walks through the follow-ups.

System design

39. “Design an image cache.”

What is scored: layers and pressure.

Senior answer: Memory cache with a cost limit, disk cache by URL, deduplicated in-flight loads, cancellation on reuse, and downsampling to display size at decode time, off the main thread. If I use NSCache I do not call it LRU: it evicts under memory pressure without a strict ordering contract.

40. “Design a paginated feed.”

What is scored: paging and state.

Senior answer: Cursor-based paging, prefetch near the end, a local store for fast launch, and explicit states for loading more, end of list and errors.

41. “Design offline sync.”

What is scored: source of truth.

Senior answer: Local database first, a durable outbox for writes, retries with idempotency keys, a stated conflict rule, and pending states in the UI. For user-written text I avoid whole-record last write wins, which silently destroys edits; I merge per field or keep both versions for the user to resolve.

42. “How would you design real-time chat on iOS?”

What is scored: connection lifecycle.

Senior answer: A WebSocket while in the foreground, push notifications in the background, local persistence with message states for sending, sent and failed, and resync by last seen id on reconnect.

43. “How do you roll out a risky feature safely?”

What is scored: release judgement.

Senior answer: Behind a remote flag, to a small percentage first, with crash and metric gates, and a kill switch that does not need an app update.

The full walkthroughs are in the iOS system design interview guide. Start every answer with requirements, never with boxes.

Testing and tooling

44. “How do you test async code?”

What is scored: determinism.

Senior answer: Async test functions that await results, with injected clocks and fake clients, so no test depends on sleeping or on the network. I also test cancellation and that a stale result arriving late is ignored.

45. “Swift Testing or XCTest?”

What is scored: awareness of current tools.

Senior answer: Swift Testing for new unit tests, with @Test, #expect and parameterized tests. XCTest is still needed for UI tests and performance tests, and both run side by side.

46. “What would you put in CI for an iOS app?”

What is scored: practical pipeline.

Senior answer: Build and unit tests on every pull request, lint, a small UI test suite on main, and automated signing and upload for release builds.

47. “How do you debug a crash you cannot reproduce?”

What is scored: method.

Senior answer: Symbolicated crash reports, grouping by device and OS, breadcrumbs from logs, and a hypothesis I can test with added logging in the next release.

A candidate who talks about tests while designing, rather than after, stands out in every round, not just this one.

Behavioural

48. “Tell me about a project you are proud of.”

What is scored: your role and impact.

Senior answer: Name the problem, your specific part, a hard decision you made and why, and a measurable result. Say “I” for your work and “we” for the team’s.

49. “Describe a decision you pushed back on.”

What is scored: constructive disagreement.

Senior answer: Explain both views fairly, how you tested yours, the outcome, and how you committed to the decision even if it went the other way.

50. “How do you help a struggling teammate?”

What is scored: mentoring at senior level.

Senior answer: Find out what is blocking them first, pair on a real task, give small, specific feedback, and make their progress visible to others.

Behavioural answers need real stories. Write down four from your own work before the loop, and you can shape each to fit most of these questions.

What changed in 2024 to 2026

  • Swift 6.2 shipped on 15 September 2025 with what the Swift team calls approachable concurrency (Swift.org, Swift 6.2 released).
  • A module can opt in to main actor isolation by default, so its code runs on the main actor without @MainActor written on every type.
  • The new @concurrent attribute marks a function that should run concurrently, which makes it visible in the code when work leaves the actor.

Sources

The official documentation is the tie breaker for every technical claim here, and it is worth a skim for any API you plan to mention by name.

What to do next

Mark every question you hesitated on, then answer only those aloud tomorrow. Fifty is too many to drill equally, and the gaps are where the loop is decided.

Free guide: the Phoenix Method