Interview · UIKit · SwiftUI
UIKit and SwiftUI interview questions that actually come up
The questions iOS interviews actually ask, answered in a sentence or two, with the trap hidden in each one. No 400-question dump.
UIKit
1 · Frame vs. bounds
- Frame: the view's rectangle in its superview's coordinate space.
- Bounds: the same size in the view's own coordinate space, origin usually
0,0.
Rotate a view and the bounds stay put while the frame grows to contain it. Trap: you move a view with frame or center. Changing bounds.origin scrolls its contents instead.
2 · UIViewController lifecycle
viewDidLoad: runs once, for one-time setup.viewWillAppear/viewDidAppear: run every time the view shows, so refresh data here.viewDidLayoutSubviews: runs after Auto Layout computes frames, so read geometry here.
Trap: don't do frame-dependent work in viewDidLoad, because the view isn't sized for the real screen yet.
3 · Cell reuse
Lists recycle a small pool of cells, so a dequeued cell still holds the previous row's content and any in-flight image load. Reset it in prepareForReuse() by clearing the image and cancelling the download, or you get the wrong image flashing in the wrong row during fast scroll.
4 · Content hugging vs. compression resistance
- Content hugging: how hard the view resists growing past its content size.
- Compression resistance: how hard it resists shrinking below it.
In a tight row of two labels, the one with lower compression resistance truncates, and the one with lower hugging stretches.
5 · Retain cycles
A retain cycle is two objects strongly referencing each other, so ARC never frees them. In UIKit they hide in two places:
- Closures capturing
self: break the cycle with[weak self]. - Strong delegates: declare the delegate
weak var.
Then weak vs unowned:
weak: use when the reference can becomenil. This is the safe default.unowned: use only when the object is guaranteed to outlive the closure.
6 · When to still choose UIKit in 2026
Reach for UIKit when you need control the declarative layer doesn't cleanly expose:
- Highly custom collection view layouts.
- Interruptible, interactive transitions.
- Precise text input and editing.
- A large existing UIKit codebase not worth rewriting.
Reach for SwiftUI for most new screens and cross-platform work. It's rarely all or nothing, since real apps embed one inside the other.
SwiftUI
7 · @State / @Binding / @StateObject / @ObservedObject
It comes down to ownership:
@State: owns local, value-type state.@Binding: a two-way reference to state someone else owns.@StateObject: owns a reference type and creates it once.@ObservedObject: uses a reference type owned elsewhere, with no lifetime guarantee.
Trap: use @ObservedObject where you needed @StateObject and a parent re-render silently resets the object's state.
8 · @Observable vs. ObservableObject
Since iOS 17 the @Observable macro replaces ObservableObject plus @Published. Two wins to name:
- Less boilerplate: mark the class
@Observableand plain stored properties become observable, with no@Publishedon each. - Finer-grained updates: a view re-renders only when a property it actually reads changes, not on every change.
Own the model with @State, and make bindings with @Bindable.
9 · @EnvironmentObject vs. @Environment
@EnvironmentObject: injects a shared observable object you supplied.@Environment: reads environment values like\.colorSchemeor\.dismiss.
Trap: a missing @EnvironmentObject is a runtime crash, not a compile error.
10 · Why views are structs
A view is a cheap, disposable description of UI that SwiftUI recreates constantly. Value types make that churn fast and rule out shared-mutable-state bugs. State that must persist lives outside the struct, in the storage @State manages.
11 · What triggers a redraw
SwiftUI re-runs body, diffs the new view tree against the old, and updates only what changed. That needs identity, of two kinds:
- Structural identity: a view's position in the tree. This is why an
ifbranch can silently reset state. - Explicit identity:
Identifiableoridin aForEach. Array-index ids over a mutating list animate the wrong row.
12 · NavigationStack vs. NavigationView
NavigationView is deprecated. NavigationStack (iOS 16+) is data-driven: you bind it to a path array, so navigation becomes state you can push, pop to root, or restore a deep link by assigning to it.
13 · Mixing UIKit and SwiftUI
- SwiftUI inside UIKit: wrap it in a
UIHostingController. - UIKit inside SwiftUI: conform to
UIViewRepresentable.
Follow-up: data flows down through updateUIView and back up through a Coordinator writing to a @Binding.
Fundamentals both tracks test
14 · Struct vs. class
- Structs are value types: copied on assignment, independent, thread-safe by default.
- Classes are reference types: shared instance, identity, inheritance.
Default to structs. Trap: let on a class freezes the reference, not the object, so you can still mutate its var properties.
15 · ARC, weak vs. unowned
Compile-time reference counting frees a class instance when its strong count hits zero. Value types don't need it. The two non-strong references:
weak: doesn't retain, and becomesnilwhen the object is freed, so it must be optional.unowned: doesn't retain, is non-optional, and crashes if accessed after deallocation.
16 · async/await vs. GCD, and actors
- async/await: reads top to bottom, and
awaitsuspends without blocking the thread. - actor: serialises access to its mutable state to prevent data races.
@MainActor: pins work to the main thread for UI.
Follow-up: GCD isn't dead. async/await is built on it, and you'll still maintain DispatchQueue code.
What each question is really testing
| When they ask | They're really checking |
|---|---|
| Frame vs. bounds | Do you understand coordinate systems, or memorise a sentence |
| Cell reuse | Have you shipped a real list and hit the stale-content bug |
| State vs. StateObject | Do you understand ownership and lifetime |
| @Observable | Are you current with iOS 17+, or writing 2021 SwiftUI |
| What triggers a redraw | Do you grasp identity and diffing |
| Struct vs. class | Do you have judgement about when each fits |
For every one, don't stop at the definition. Say what it's for, name what breaks without it, and volunteer the follow-up. That's the difference between reading a list like this and having shipped.
Interviewing for a senior iOS role?
I run mock interviews and prep, covering these questions plus system design and the behavioural round. First session is free.
Book a free 1:1 Connect on LinkedIn