Lab 12.3 — Mock Technical Interview
Goal: simulate a full 60-minute senior iOS technical interview, alone or with a partner, with self-grading rubrics.
Time: 60 min interview + 15 min self-debrief = 75 min total.
Prereqs: Quiet room, Xcode or a web Swift playground (https://swiftfiddle.com), timer, recording device.
Setup
If solo: record yourself (audio + screen). If with a partner: they read prompts and play interviewer.
Pick one of three difficulty paths below before starting.
Format
0:00 – 5:00 Warm-up Q&A (3 conceptual questions, ~90 sec each)
5:00 – 35:00 Live coding (one of the prompts below)
35:00 – 50:00 System design (lighter version of one Phase 12.9 scenario)
50:00 – 60:00 Behavioral (one STAR-style question)
Warm-up Q&A bank — pick 3
- Difference between
@State,@StateObject,@ObservedObject, and@Environment? - How does
actorprevent data races, and what’s reentrancy? - When would you choose
classoverstruct? - Walk me through
URLSession.shared.data(from:)from start to finish. - What problem does SwiftData solve that Core Data didn’t?
- Explain
Sendableand Swift 6 strict concurrency in one minute. - Difference between
weakandunowned? - How does
@Observablediffer fromObservableObject? - What’s the responder chain in UIKit?
- How do you debug a retain cycle in a SwiftUI app?
Score each answer L1/L2/L3 per 12.8.
Live coding — pick one difficulty
Easy (target: junior/mid)
Implement a
Debounceractor in Swift Concurrency. It should let callers schedule an async closure to run after N milliseconds of inactivity. Each new call cancels the previously scheduled run.
Bonus: write a unit test using Task.sleep proving rapid successive calls only fire once.
Medium (target: mid/senior)
Implement an LRU cache generic over
Key: HashableandValue. Constructor takes capacity.get(_:)returns optional value and bumps recency.set(_:_:)inserts or updates; evicts least-recently-used when over capacity. All operations O(1).
Bonus: make it thread-safe via an actor variant.
Hard (target: senior/staff)
Implement a
RateLimiteractor: a token bucket allowing N requests per T seconds. Methodacquire()is async — returns immediately if a token is available, or waits until one is. Cancellation must clean up waiters.
Bonus: support priority — high-priority callers jump the queue.
Live coding self-grading rubric
| Dimension | 0 (poor) | 1 (passable) | 2 (strong) |
|---|---|---|---|
| Clarifying questions | None asked | 1–2 generic | 3+ specific, written down |
| Narration | Silent typing | Some narration, gaps | Continuous; thinking audible |
| Type signature first | No | Yes, but inconsistent | Yes, explicit, justified |
| Tests / verification | None | Manually walked through | At least one sanity test |
| Tradeoff awareness | None mentioned | One in passing | Multiple explicit |
| Recovery from stuck | Silent or gave up | Asked for hint | Verbalized obstacle, simplified, asked for hint |
| Code correctness | Doesn’t compile | Compiles, has bugs | Compiles and runs correctly |
| Code clarity | Hard to read | Readable | Idiomatic, self-documenting |
Pass bar for senior level: average ≥ 1.5 with no dimension at 0.
System design — pick one
Choose one scenario from 12.9 (Instagram Feed, Real-Time Chat, Offline Note App, Maps, Video Streaming) and discuss for 15 min covering:
- 3 clarifying questions (record what you’d ask)
- High-level architecture sketch
- iOS-specific deep-dive on data layer + state + concurrency
- Two tradeoffs you’d flag to interviewer
- What changes at 10× scale
Grade against the rubric:
| Dimension | 0 | 1 | 2 |
|---|---|---|---|
| Clarifying | Skipped | Generic | Specific to scope |
| iOS focus | Server-heavy | Mixed | Predominantly iOS |
| Tradeoff verbalization | None | One | Multiple, named |
| Scaling discussion | None | Hand-wavy | Concrete (CDN, sharding, etc.) |
| Offline / background concerns | Ignored | Mentioned | Designed for |
Behavioral — pick one
- Tell me about a time you owned a difficult technical decision.
- Tell me about your hardest bug.
- Tell me about a time you disagreed with a designer or PM.
- Tell me about a project that failed and what you learned.
- Why do you want to work here? (research a real company)
Use a STAR template from 12.11. 90-second timer.
Self-grade:
| Dimension | 0 | 1 | 2 |
|---|---|---|---|
| STAR structure | Missing pieces | All present, weak transitions | All present, smooth |
| “I” language | Mostly “we” | Mixed | Mostly “I” with team context |
| Concrete result | None | Vague (“it went well”) | Specific number / outcome |
| Time discipline | > 2 min | 90 s – 2 min | < 90 s |
Debrief (15 min)
- Re-listen to your recording.
- Score each section using the rubrics above.
- Identify the single weakest area.
- Pick one action to improve next week.
Common weak areas and remedies:
| Weak area | Remedy |
|---|---|
| Silent live coding | Practice narrating while doing daily work tasks |
| Skipped clarifications | Write the 5 standard questions on a sticky note next to your monitor |
| Vague STAR results | Rewrite stories with measurable outcomes; verify numbers |
| Wandering system design | Time-box each section in a 4×4 grid: clarify / architecture / iOS deep dive / tradeoffs |
| Defensive when corrected | Practice the “you’re right, I missed that” acknowledgment phrase aloud |
Stretch
- Run the same exercise 4 weeks running. Track scores. Look for the inflection point (typically week 3) where it stops feeling unnatural.
- Pair with a peer; switch interviewer/candidate roles each week.
- Record yourself answering a single behavioral question 5 times in a row, listening to each playback. By the fifth, it’ll be tight.
Notes
The single most valuable feedback comes from listening to your own recording. You will cringe. That’s the data; iterate on it. Most candidates skip recording and then wonder why interviews don’t go well — they’ve never heard themselves under simulated pressure.