SwiftUI Interview Questions & Answers
This set covers 88 SwiftUI interview questions with point-wise answers, written from a working iOS developer's point of view. Each answer is concise and structured the way you should speak in an interview.
SwiftUI Fundamentals
1. What is SwiftUI?
- Apple's declarative UI framework for building interfaces across all Apple platforms.
- You describe what the UI should look like for a given state, not how to mutate it.
- The framework diffs and updates the view tree automatically.
- It works alongside UIKit, not as a hard replacement.
2. What is the difference between declarative and imperative UI?
- Imperative UI (UIKit) mutates view objects step by step.
- Declarative UI (SwiftUI) describes the UI as a function of state.
- Declarative code reduces manual synchronisation bugs.
- When state changes, SwiftUI re-renders the affected views for you.
3. What is a View in SwiftUI?
- A
Viewis a protocol with a singlebodycomputed property. bodyreturns the view's content as other views.- Views are lightweight value types, recreated cheaply on each update.
- They are descriptions of UI, not the actual rendered objects.
4. Why are SwiftUI views structs and not classes?
- Structs are value types, so they are cheap to create and copy.
- Immutability makes view diffing predictable and fast.
- There is no shared mutable state to cause subtle UI bugs.
- State that must persist is stored separately via property wrappers.
5. What is the body property?
- It is the required computed property describing a view's content.
- SwiftUI calls it whenever the view needs to re-render.
- It must return a single view (often a container holding many).
- Keep it cheap because it can run frequently.
6. What is the difference between VStack, HStack, and ZStack?
VStackarranges children vertically.HStackarranges children horizontally.ZStackoverlays children back-to-front.- They are the core layout primitives you compose UIs from.
7. What are view modifiers?
- Methods that return a new, modified copy of a view.
- Examples:
.padding(),.foregroundColor(),.frame(). - They are chained, and order matters to the result.
- Each modifier wraps the view in a new layer.
8. Why does modifier order matter?
- Each modifier acts on the result of the previous one.
.padding().background()differs from.background().padding().- The first colours outside the padding; the second inside it.
- Think of modifiers as wrapping the view in successive boxes.
9. What is some View and opaque return types?
some Viewmeans "a specific concrete type I won't name".- It lets
bodyreturn complex nested types without spelling them out. - The compiler knows the exact type; the caller only knows it conforms to
View. - It keeps APIs clean while preserving type safety.
10. What is ViewBuilder?
- A result builder that lets you list multiple views inside a closure.
- It powers the declarative syntax inside stacks and containers.
- It supports limited control flow like
ifandswitch. - It combines child views into a single composite view.
State Management
11. What is @State?
- A property wrapper for simple, view-local mutable state.
- SwiftUI owns the storage and re-renders when it changes.
- Mark it
privatesince it belongs to that view. - Use it for value types like toggles, counters, and text.
12. What is @Binding?
- A two-way reference to state owned by another view.
- It lets a child read and write the parent's value.
- Create one with the
$prefix on a@Stateproperty. - It avoids duplicating state across the hierarchy.
13. What is the difference between @State and @Binding?
@Statedeclares and owns the source of truth.@Bindingis a reference to state owned elsewhere.- Parents hold
@State; children receive a@Binding. - This keeps a single source of truth shared safely.
14. What is @StateObject?
- Owns and keeps alive a reference-type observable object.
- SwiftUI creates it once and persists it across re-renders.
- Use it where the object is first created.
- It prevents accidental re-instantiation on each render.
15. What is @ObservedObject?
- Subscribes to an observable object owned elsewhere.
- The view re-renders when the object publishes changes.
- It does not own the object's lifecycle.
- Recreating the parent can reset an
@ObservedObject, unlike@StateObject.
16. What is the difference between @StateObject and @ObservedObject?
@StateObjectowns and persists the object across view updates.@ObservedObjectjust observes an externally owned object.- Use
@StateObjectat the creation site,@ObservedObjectwhen passing it in. - Misusing
@ObservedObjectat creation can cause object loss on re-render.
17. What is @EnvironmentObject?
- Injects a shared observable object into the view hierarchy.
- Any descendant can read it without manual passing.
- It avoids prop-drilling through many intermediate views.
- The object must be supplied with
.environmentObject()up the tree.
18. What is the @Environment property wrapper?
- Reads system-provided values from the environment.
- Examples:
\.colorScheme,\.dismiss,\.locale. - Values propagate down the view tree automatically.
- You can also define custom environment keys.
19. What is the ObservableObject protocol?
- A protocol for reference types that publish changes.
- Mark properties with
@Publishedto trigger updates. - Views observing it re-render when those properties change.
- It is the classic backbone of a SwiftUI view model.
20. What is @Published?
- A property wrapper that emits a change before a property updates.
- It works inside an
ObservableObject. - Subscribed views refresh automatically.
- It is built on Combine's publisher mechanism.
21. What is the new @Observable macro?
- A macro (iOS 17+) replacing
ObservableObject+@Published. - It tracks property access so only views using a property re-render.
- It reduces boilerplate and improves performance.
- Pair it with
@Stateor@Bindablein views.
22. What is the "single source of truth" principle?
- Each piece of state should live in exactly one place.
- Other views reference it via bindings, not copies.
- It prevents inconsistent, conflicting UI state.
- It is central to predictable SwiftUI data flow.
23. What is @AppStorage?
- A wrapper that reads and writes
UserDefaultsvalues. - Changes automatically update views and persist across launches.
- Great for simple settings like theme or onboarding flags.
- Do not use it for large or sensitive data.
24. What is @SceneStorage?
- Persists small UI state tied to a scene for restoration.
- Useful for restoring tab selection or scroll position.
- The system manages saving and restoring it.
- It is per-scene, unlike app-wide
@AppStorage.
25. When does a SwiftUI view re-render?
- When state it depends on (
@State, observed objects, bindings) changes. - SwiftUI recomputes
bodyand diffs the result. - Only the parts that actually changed are redrawn.
- Unrelated state changes should not trigger a redraw.
Layout & Lists
26. How does SwiftUI's layout system work?
- A parent proposes a size; the child chooses its own size; the parent positions it.
- This negotiation flows down and back up the tree.
- Layout is reactive and adapts to content and space.
- Understanding the proposal cycle explains most layout surprises.
27. What is a GeometryReader?
- A container that exposes its proposed size and coordinate space.
- Use it to build size- or position-dependent layouts.
- It greedily takes all offered space, which can surprise layouts.
- Use sparingly; prefer simpler layout tools when possible.
28. What is the difference between frame and fixedSize?
.frame()proposes a specific size to a view..fixedSize()lets a view size to its ideal content, ignoring compression.fixedSizeprevents text truncation by allowing full intrinsic size.- Combine them to control sizing precisely.
29. What is the difference between Spacer and padding?
Spacerexpands to push siblings apart within a stack..padding()adds fixed space around a single view.- Spacer is flexible; padding is a defined amount.
- Use spacers for distribution, padding for breathing room.
30. How do you build a list in SwiftUI?
- Use
Listwith static rows or a data collection. - For dynamic data, provide an
idor useIdentifiable. - It handles scrolling, separators, and reuse automatically.
- It is the SwiftUI counterpart to
UITableView.
31. What is the Identifiable protocol and why does List need it?
- It requires a stable
idproperty uniquely identifying each item. - SwiftUI uses the id to track, diff, and animate rows.
- Without stable ids, rows can glitch or animate wrongly.
- You can also pass a key path via
id:instead.
32. What is the difference between ForEach and a for loop?
ForEachis a view that generates child views from data.- A normal
forloop runs imperatively and cannot return views directly. ForEachneeds identifiable data for diffing.- It is used inside stacks, lists, and grids.
33. What is LazyVStack versus VStack?
VStackcreates all children immediately.LazyVStackcreates children only as they scroll into view.- Lazy variants save memory and improve performance for long content.
- Use lazy stacks inside a
ScrollViewfor large datasets.
34. How do you create a grid in SwiftUI?
- Use
LazyVGrid/LazyHGridwithGridItemcolumn definitions. GridItemcan be fixed, flexible, or adaptive.- For simpler aligned layouts,
Grid(iOS 16+) is available. - Lazy grids render cells on demand for performance.
35. How do you add swipe actions or pull-to-refresh to a List?
- Use
.swipeActionson rows for leading/trailing buttons. - Use
.refreshableon the list for pull-to-refresh. .refreshableworks naturally with async/await.- These modifiers replace manual UIKit gesture wiring.
Navigation & Presentation
36. How does navigation work in SwiftUI?
- Wrap content in a
NavigationStack(iOS 16+). - Use
NavigationLinkto push destinations. - A bound path array enables programmatic navigation.
- It replaces UIKit's
UINavigationControllerpush/pop.
37. What is the difference between NavigationView and NavigationStack?
NavigationViewis the older, now-deprecated container.NavigationStackoffers a clear, path-driven model.NavigationStacksupports type-safe, programmatic navigation.- New apps should prefer
NavigationStack.
38. What is a NavigationLink?
- A control that pushes a destination when tapped.
- It can take a value resolved by
navigationDestination. - It integrates with the navigation path for programmatic control.
- Use it inside a navigation container.
39. How do you present a sheet (modal)?
- Use the
.sheet(isPresented:)or.sheet(item:)modifier. - Toggle a bound boolean or set an identifiable item to show it.
- SwiftUI handles the modal presentation and dismissal.
- Use
.fullScreenCoverfor a full-screen modal.
40. How do you dismiss a view programmatically?
- Read
@Environment(\.dismiss)and call it. - For bound presentation, set the boolean back to
false. - This works for sheets and pushed views alike.
- It replaces UIKit's manual
dismiss/popcalls.
41. What is a TabView?
- A container presenting tabbed content with a tab bar.
- Each tab gets a label via
.tabItem. - It supports a
selectionbinding for programmatic switching. - It also powers paged carousels with the page style.
42. How do you show an alert or confirmation dialog?
- Use the
.alertmodifier bound to a boolean or item. - Use
.confirmationDialogfor action-sheet style choices. - Provide buttons and an optional message inside.
- SwiftUI manages presentation declaratively from state.
43. How do you pass data during navigation?
- Pass values into the destination view's initialiser.
- With value-based navigation, attach a
navigationDestinationhandler. - Shared state can flow via environment or a view model.
- Avoid global singletons for better testability.
44. What is deep linking and how is it handled?
- Opening a specific screen from a URL or notification.
- Use
.onOpenURLto parse and route the link. - Drive a
NavigationStackpath to reach the target screen. - Value-based navigation makes this clean and testable.
45. How do you handle navigation in a large app?
- Centralise navigation state in a router/coordinator object.
- Use a bound path array for programmatic control.
- Represent destinations as an enum for type safety.
- This keeps deep links and back navigation manageable.
Animations & Gestures
46. How do animations work in SwiftUI?
- SwiftUI animates the difference between two states automatically.
- Wrap a state change in
withAnimation { }or attach.animation(). - It interpolates affected properties like position, size, and opacity.
- You describe the end state; SwiftUI animates the transition.
47. What is the difference between implicit and explicit animation?
- Implicit uses the
.animation(_:value:)modifier tied to a value. - Explicit wraps a state change in
withAnimation { }. - Implicit animates whenever that value changes.
- Explicit animates only the changes inside the closure.
48. What is a transition in SwiftUI?
- It defines how a view appears and disappears.
- Examples:
.opacity,.slide,.scale, or custom ones. - Applied with
.transition()on views added or removed. - The insertion/removal must occur inside an animation.
49. What is matchedGeometryEffect?
- It animates a view smoothly between two positions in a shared namespace.
- SwiftUI matches the source and destination by id.
- It powers hero-style transitions between layouts.
- Both views must use the same
@Namespace.
50. How do you handle gestures in SwiftUI?
- Attach gesture modifiers like
.onTapGestureor.gesture(). - Built-in gestures include tap, drag, long press, and magnify.
- Combine gestures with
simultaneously,sequenced, orexclusively. - Gesture state can drive animations and view updates.
51. What is a DragGesture?
- A gesture that reports translation as the user drags.
- Use
onChangedfor live updates andonEndedto finalise. - Combine with
@GestureStatefor automatic reset. - Common for swipe, slide, and pull interactions.
52. What is @GestureState?
- A wrapper that tracks transient gesture state.
- It automatically resets to its initial value when the gesture ends.
- Ideal for in-progress drag offsets.
- It avoids manual cleanup after the gesture finishes.
53. How do you create a custom animation curve?
- Use built-ins like
.easeInOut,.spring, or.timingCurve. .springgives natural, physics-based motion.- Adjust duration, damping, and response for the feel you want.
- Apply the curve through
withAnimationor.animation().
Combine, Async & Data
54. How do you load data asynchronously in SwiftUI?
- Use the
.task { }modifier, which runs async work when a view appears. - Await network or database calls inside it.
- It cancels automatically when the view disappears.
- Store results in observable state to update the UI.
55. What is the difference between .task and .onAppear?
.onAppearruns synchronous code when a view appears..taskruns async work and ties it to the view's lifetime..taskauto-cancels when the view goes away.- Prefer
.taskfor async loading to avoid manual cancellation.
56. How does Combine integrate with SwiftUI?
- Publishers feed values into
@Publishedproperties. - Views observing the object refresh on emissions.
onReceivelets a view react to any publisher.- Much of this is now replaceable by async/await and
@Observable.
57. What is the onReceive modifier?
- It subscribes a view to a Combine publisher.
- The closure runs each time the publisher emits.
- Useful for timers, notifications, or external streams.
- SwiftUI handles subscription lifecycle for you.
58. How do you debounce user input like a search field?
- With Combine, apply
debounceon the text publisher. - With async, use a debounced
Taskthat cancels prior work. - It avoids firing a request on every keystroke.
- This reduces network load and improves responsiveness.
59. How do you bind a text field to state?
- Pass a
@Statestring via its binding:TextField("", text: $name). - Typing updates the state and re-renders dependent views.
- The binding keeps UI and data in sync two-way.
- Use
@FocusStateto manage keyboard focus.
60. What is @FocusState?
- A wrapper tracking which field currently has keyboard focus.
- Bind it to fields to read or programmatically set focus.
- Useful for moving focus between form fields.
- It replaces UIKit first-responder management.
Interoperability & Architecture
61. How do you use a UIKit view in SwiftUI?
- Wrap it with
UIViewRepresentable. - Implement
makeUIViewandupdateUIView. - Use a
Coordinatorto handle delegates and callbacks. - This bridges mature UIKit components into SwiftUI.
62. How do you use a UIViewController in SwiftUI?
- Wrap it with
UIViewControllerRepresentable. - Implement the make/update controller methods.
- Use it for things like camera, web views, or existing screens.
- A coordinator handles delegate callbacks.
63. How do you embed SwiftUI inside a UIKit app?
- Wrap a SwiftUI view in a
UIHostingController. - Push or present that controller like any other.
- It lets you adopt SwiftUI incrementally.
- State and data can be passed in at creation.
64. What is the Coordinator pattern in representables?
- A class that bridges UIKit delegate callbacks back to SwiftUI.
- Created in
makeCoordinator(). - It holds references to bindings and forwards events.
- It is how imperative UIKit talks to declarative SwiftUI.
65. Which architecture patterns suit SwiftUI?
- MVVM fits naturally with observable view models.
- The Composable Architecture (TCA) offers stricter unidirectional flow.
- Plain MV (model + view) works for simpler apps.
- Choose based on app size and team preference.
66. Why does MVVM fit SwiftUI well?
- View models expose observable state the view binds to.
- Views stay thin and declarative.
- Business logic is testable outside the UI.
- It aligns with SwiftUI's reactive data flow.
67. How do you inject dependencies in SwiftUI?
- Pass them into view-model initialisers.
- Use the environment for app-wide services.
- Define custom environment keys for clean access.
- This enables mocking for previews and tests.
68. How do you share state across the whole app?
- Create an observable object and inject it with
.environmentObject(). - Descendants read it with
@EnvironmentObject. - Keep it focused to avoid over-broad re-renders.
- For iOS 17+, use
@Observablewith the environment.
Performance, Previews & Testing
69. How do you optimise SwiftUI performance?
- Keep
bodycheap and split large views into smaller ones. - Use lazy stacks and grids for long content.
- Scope observable state so only affected views re-render.
- Avoid heavy work and
GeometryReaderwhere unnecessary.
70. Why is splitting large views into smaller ones beneficial?
- SwiftUI re-renders only views whose state changed.
- Smaller views localise updates and reduce wasted work.
- They are easier to read, reuse, and test.
- It limits how much
bodyrecomputes at once.
71. What causes unnecessary re-renders and how do you avoid them?
- Observing too broad an object refreshes unrelated views.
- Passing changing closures or values can invalidate views.
- Use fine-grained observation (
@Observable) and stable identities. - Split state so changes touch the minimum view set.
72. What are SwiftUI Previews?
- Live, interactive canvas renders of a view in Xcode.
- They speed iteration without running the full app.
- You can preview multiple states, devices, and color schemes.
- Inject sample data so previews stay isolated.
73. How do you preview multiple states or devices?
- Return several views from the preview, each with different data.
- Apply
.preferredColorSchemeor device traits. - Use the
#Previewmacro (Xcode 15+) for concise setup. - This validates light/dark and size variations quickly.
74. How do you make a view accessible in SwiftUI?
- Add
.accessibilityLabeland.accessibilityHint. - Group related elements with
.accessibilityElement(children:). - Support Dynamic Type by using scalable fonts.
- Test with VoiceOver and large text settings.
75. How does SwiftUI support Dynamic Type?
- System text styles scale automatically with the user's setting.
- Use
.font(.body)rather than fixed point sizes. - Layouts should adapt to larger text without clipping.
- Test at the largest accessibility sizes.
76. How do you support dark mode?
- Use semantic colors and system materials that adapt automatically.
- Read
@Environment(\.colorScheme)when you need to branch. - Provide asset-catalog colors with light/dark variants.
- Preview both schemes to verify contrast.
77. How do you localise a SwiftUI app?
- Use string keys resolved from
Localizable.strings. Textautomatically looks up localised values.- Support right-to-left layouts with leading/trailing alignment.
- Format numbers and dates with locale-aware formatters.
78. How do you test SwiftUI views?
- Unit-test view models and logic directly with XCTest.
- Use UI tests or snapshot tests for view output.
- Keep logic out of views to maximise testability.
- Previews also serve as quick visual checks.
Advanced & Cross-Platform
79. How does SwiftUI handle different Apple platforms?
- The same view code can target iOS, macOS, watchOS, and tvOS.
- Platform-specific modifiers adapt behaviour where needed.
- Conditional compilation handles differences.
- It maximises code sharing across devices.
80. What is the @ViewBuilder attribute used for in custom views?
- It lets your custom container accept multiple child views.
- Apply it to a closure parameter to build content.
- It mirrors how built-in stacks accept children.
- It enables reusable, composable container components.
81. What is a PreferenceKey?
- A mechanism to pass data up from child views to ancestors.
- Children set a preference; an ancestor reads it.
- Useful for measuring sizes or coordinating layout.
- It complements the environment, which flows downward.
82. What is the difference between environment and preferences?
- Environment values flow downward to descendants.
- Preferences flow upward from descendants to ancestors.
- Use environment to configure children, preferences to report from them.
- Together they enable two-way coordination.
83. How do you create a custom ViewModifier?
- Conform a struct to
ViewModifierand implementbody(content:). - Apply it with
.modifier()or a convenience extension. - It packages reusable styling and behaviour.
- It keeps view code DRY and consistent.
84. How do you draw custom shapes and paths?
- Conform a struct to
Shapeand implementpath(in:). - Use
Pathcommands to build lines and curves. - Apply fills, strokes, and gradients as modifiers.
- Shapes animate when their parameters are animatable.
85. What is Canvas in SwiftUI?
- A view for immediate-mode, high-performance custom drawing.
- You draw directly in a closure with a graphics context.
- Good for charts, particles, or many dynamic shapes.
- It avoids the overhead of many individual views.
86. How do you persist data with SwiftData in SwiftUI?
- Define models with the
@Modelmacro. - Query them in views with
@Query. - Insert into and save through the model context.
- It integrates cleanly with SwiftUI's lifecycle.
87. What are common SwiftUI pitfalls to avoid?
- Using
@ObservedObjectwhere@StateObjectis needed. - Overusing
GeometryReaderand bloatingbody. - Putting business logic directly in views.
- Ignoring view identity, causing animation glitches.
88. When should you choose SwiftUI over UIKit?
- Choose SwiftUI for new apps and rapid, cross-platform UI.
- Use UIKit when you need mature, fine-grained control or legacy support.
- Mixed apps are common, bridging both with representables.
- Consider team familiarity and minimum OS target.