Interview guides / ios
Senior iOS Engineer Interview Questions
Senior iOS interview questions spanning architecture, concurrency, performance, offline sync, and leadership-style technical judgment.
Senior iOS rounds go beyond syntax. Interviewers look for ownership boundaries, concurrency safety, performance instincts, and tradeoff clarity.
Expect deeper follow-ups: Why this architecture? What fails offline? How do you measure jank? How do you roll back a bad release?
1.How do you structure a large iOS codebase for multiple teams?
Feature modules with clear API boundaries, shared cores for networking/storage/design system, and no feature-to-feature imports. Use coordinators/routers for navigation. Keep auth and analytics as injected services. Optimize for independent ownership and build times, not perfect purity.
2.How do you reason about concurrency bugs in production?
Prefer Swift Concurrency with actor isolation and MainActor for UI. Reproduce with thread sanitizer / stress tests where possible. Look for shared mutable state crossing queues, escaping closures without capture lists, and UI updates off main. Add breadcrumbs and crash signatures that include queue/isolation context.
3.What does a senior-level offline strategy look like?
Local source of truth, outbox for mutations, explicit stale UI, conflict policy documented as product behavior, and telemetry on sync failure rates. Seniors can explain what is intentionally out of scope for an MVP versus what becomes dangerous at scale.
4.Walk through the UIViewController lifecycle and where you would load data, configure UI, and clean up observers.
loadView → viewDidLoad (one-time setup) → viewWillAppear → viewIsAppearing → viewDidAppear → viewWillDisappear → viewDidDisappear → deinit. Load remote data after first appear or via a dedicated loader; remove NotificationCenter/KVO observers in deinit or viewDidDisappear depending on scope; cancel in-flight tasks when the screen disappears if results are no longer needed.
5.When do you pick delegate patterns vs completion closures?
Delegates suit multi-method ongoing relationships (tableView). Closures suit one-shot results. Avoid retain cycles: weak delegates, weak self captures.
6.What does iOS sandboxing restrict?
Apps can’t freely read other apps’ data; limited filesystem, entitlements for capabilities (iCloud, push, associated domains). Privacy manifests/permissions gate sensitive APIs.
7.What are common NotificationCenter bugs and how do you avoid them?
Forgetting to remove observers (pre-block API), posting on wrong threads, overusing global events. Prefer Combine publishers, delegates, or scoped observers; always consider lifecycle.
8.What is KVO and what replaced it in many Swift codebases?
KVO observes Obj-C property changes. Prefer Combine, Observation/@Observable, delegates, or closures for Swift-first code. KVO still appears with AVFoundation and legacy APIs.
9.How does cell reuse work and what bugs does it cause?
Cells dequeue from a reuse pool; configure every visible field in cellForRow or configure methods. Stale images/text appear if you don’t reset state; cancel image loads on prepareForReuse.
10.When would you use Result<Success, Failure> instead of throws?
Result is great for async callbacks and stored outcomes. throws fits synchronous APIs and async/await. You can bridge with get() / mapError depending on call site style.
11.How do optionals work, and when would you use ?, !, if let, guard let, and ??
Optionals wrap absence of a value. Prefer if let/guard let for safe unwraps; ?? for defaults; avoid force unwrap (!) except when truly impossible to be nil. Optional chaining (?.) short-circuits safely.
12.Explain value types vs reference types and how copying behaves.
Value types (struct/enum) copy on assignment; reference types share one instance. Mutations to a copy don’t affect the original. Copy-on-write optimizes large values like Array/Dictionary/String.
13.When do you choose a struct over a class in Swift?
Prefer structs for value semantics, thread-safer copies, and simple data. Use classes for identity, inheritance, Objective-C interop, or shared mutable references. Many modern models are structs; UIKit types remain classes.
14.What is ATS and when can you exception it?
ATS enforces HTTPS/TLS best practices. Exceptions via Info.plist for legacy servers are discouraged and scrutinized. Prefer fixing server TLS over broad NSAllowsArbitraryLoads.
15.Explain Automatic Reference Counting (ARC). When do retain cycles happen, and how do you break them with weak and unowned references?
ARC tracks strong references and frees objects at zero. Cycles usually appear in closures capturing self, or parent↔child object graphs. Use weak for optional back-references (delegates, closures that may outlive the object) and unowned when the reference is non-optional and guaranteed to outlive the capture. Always capture lists in escaping closures: `[weak self]`.
16.Design a photo-sharing iOS client: home feed, upload, likes, comments, profile, and push. Give a thorough client design with architecture, diagram-level components, networking, caching, offline, performance, and explicit tradeoffs.
## Overview Treat this as a modular iOS client with a local cache, optimistic engagement, resumable uploads, and clear offline degradation—not a backend-only whiteboard. Interviewers want to hear how MVVM boundaries, repositories, and sync interact under real device constraints (memory, battery, flaky networks). ## Architecture diagram ```mermaid flowchart TB subgraph UI["UI layer"] FeedView["FeedView<br/>SwiftUI/UIKit"] UploadView["Upload Composer"] ProfileView["ProfileView"] end subgraph VM["Presentation"] FeedVM["FeedViewModel"] UploadVM["UploadViewModel"] ProfileVM["ProfileViewModel"] end subgraph Domain["Domain / Data"] FeedRepo["FeedRepository"] EngageRepo["EngagementRepository"] UploadMgr["UploadManager actor"] Outbox["Outbox queue"] LocalDB[(SwiftData / Core Data)] ImageCache["Image cache<br/>NSCache + disk"] end subgraph Remote["Remote"] API["REST API"] CDN["Media CDN"] APNs["APNs"] end FeedView --> FeedVM --> FeedRepo UploadView --> UploadVM --> UploadMgr ProfileView --> ProfileVM --> FeedRepo FeedRepo --> LocalDB FeedRepo --> API FeedRepo --> ImageCache ImageCache --> CDN EngageRepo --> Outbox --> API UploadMgr --> API UploadMgr --> LocalDB APNs -.-> FeedVM ``` ## Architecture Use MVVM with feature modules (Feed, Upload, Profile, Notifications). Views stay dumb: they render state and forward intents. ViewModels own UI state (loading/paging/errors/optimistic likes) and call repositories—never URLSession directly. Introduce a Coordinator/Router for profile deep links so features do not import each other. Shared AuthSession + APIClient are injected. UploadManager should be an actor (or serial operation queue) so concurrent composers cannot corrupt the job list. Keep analytics/haptics as side-effect services invoked from ViewModels after state transitions. ## Networking Cursor-paginated feed GET; ETag/If-None-Match on refresh; idempotent like/unlike POST with client-generated keys; comments paginated separately. Media uses server-signed upload URLs (PUT) then a finalize call. APIClient: auth interceptor, single-flight token refresh, decode DTOs → domain models off the main actor. Prefetch next page when the user is ~5 items from the end. Background URLSession for large uploads that must survive app backgrounding. Cancel in-flight detail fetches when leaving a screen. Push (APNs) invalidates feed/inbox and triggers a lightweight sync—not a full refetch storm. ## Storage & caching Local DB is the cache/SoT for recently seen posts, profiles, and draft uploads. Image pipeline: memory NSCache + disk LRU with max bytes; decode at display size via ImageIO. Persist outbox rows for likes/comments. Evict old feed pages aggressively; pin “saved” posts longer. Never store access tokens in UserDefaults—Keychain only. Draft media stays on disk until server ACK, then delete or keep based on product policy. ## Offline mode Show last cached feed with an explicit stale banner and last-updated time. Likes/comments enqueue to outbox and show pending/failed affordances; flush on reconnect (NWPathMonitor). Uploads created offline remain drafts until network returns. Disable network-only surfaces (Explore/Discover) rather than faking freshness. On conflict (like count mismatch), server wins after reconciliation—roll back optimistic UI calmly. ## Performance Stable cell identities; downsample images before assign; prefetch URLs for upcoming cells; avoid main-thread image decode. Prefer diffable data sources / LazyVStack with explicit ids. Compress HEIC/JPEG before upload. Instruments: Time Profiler, Allocations, Hitches, Network. Bound concurrent decodes. Paginate comments; don’t load full comment trees into the feed cell model. ## Tradeoffs ### Optimistic likes vs server-confirmed likes **Option A — Optimistic UI:** Flip heart immediately, enqueue mutation, rollback on failure. Feels instant; requires conflict/rollback UX and careful idempotency. **Option B — Pessimistic UI:** Wait for 200 before updating. Simpler consistency; feels laggy on poor networks and trains users to tap repeatedly. **Pick A when:** Engagement is high-frequency and failures are rare/recoverable. **Pick B when:** Compliance/audit flows or when double-charges/side effects make rollback unsafe. ### Local DB as cache vs view-memory only **Option A — Persisted feed cache:** Survives process death; enables offline reading; more migration/complexity. **Option B — In-memory only:** Simple and fresh, but blank states after kills and no offline story. **Pick A when:** Offline/read-later matters and cold start UX matters. **Pick B when:** MVP throwaway prototype or highly personalized feed that is meaningless when stale. ### Background uploads vs foreground-only **Option A — Background URLSession:** Uploads continue when backgrounded; more setup (delegates, rejoin sessions) and edge cases. **Option B — Foreground only:** Easier reasoning; large uploads fail if user leaves. **Pick A when:** Media is core and uploads are multi-MB. **Pick B when:** Small images and sessions are short.
17.Design a feature-flag / remote-config system for a large iOS app: staged rollouts, kill switches, experimentation, and safe startup.
## Overview Flags must be cached-first, typed, and non-blocking at launch, with kill switches that can disable broken features without an App Store release. ## Architecture diagram ```mermaid flowchart TB App[App launch] --> Cache[Disk flag snapshot] Cache --> Snapshot[In-memory snapshot] Snapshot --> VM[Feature ViewModels] App --> Fetch[Remote Config fetch] Fetch -->|update| Snapshot Fetch -->|persist| Cache Push[Silent push] --> Fetch Defaults[Compiled defaults] --> Snapshot ``` ## Architecture FeatureFlagProvider protocol with typed keys. ViewModels depend on the provider—not NotificationCenter blasts. Experiment assignment sits beside flags. Bootstrap defaults ship in-binary for first install. ## Networking Non-blocking fetch on launch + periodic refresh + optional silent push. Short timeout; CDN JSON/protobuf; schema version field. Analytics exposures batched. ## Storage & caching Last-known-good on disk; schema migrations; unknown keys ignored; defaults always defined. ## Offline mode Offline uses cache/defaults forever; never crash on missing key; queue exposures. ## Performance O(1) dictionary reads; parse off main; atomic snapshot swap on MainActor if UI observes. ## Tradeoffs ### Cached-first vs network-first launch **Option A — Cached-first:** Instant startup using last snapshot; may be briefly stale. **Option B — Network-first:** Freshest flags; slows/blocks launch and fails offline. **Pick A when:** Consumer apps where launch time matters. **Pick B when:** Rare safety-critical configs that must be fresh (still prefer timeout+cache fallback). ### Client percentage rollout vs server targeting **Option A — Client hash of userId:** Works offline; simple; weaker abuse control. **Option B — Server decides:** Central control and richer targeting; requires network. **Pick A when:** Sticky offline experiments. **Pick B when:** Regulated targeting or rapid kill that must be server authoritative. ### Many fine-grained flags vs coarse modules **Option A — Fine-grained:** Precise control; operational sprawl and interactions. **Option B — Coarse modules:** Fewer combinations; less flexibility. **Pick A when:** Mature platform with flag hygiene. **Pick B when:** Early product—prefer fewer flags.
18.Design a robust iOS networking layer: auth, refresh, retries, errors, caching, testability.
## Overview A single APIClient with interceptor pipeline and protocol boundaries keeps features testable and consistent. ## Architecture diagram ```mermaid flowchart TB VM --> Repo --> APIClient APIClient --> Auth[Auth Interceptor] APIClient --> Retry[Retry Policy] APIClient --> Session[URLSession] Auth --> Keychain Repo --> DTO[DTO mapper] ``` ## Architecture Features depend on repositories/protocols. APIClient handles auth header, redacted logs, refresh single-flight (actor). Map transport errors to domain errors for ViewModels. ## Networking One session config; refresh-on-401 once; retry idempotent GETs only by default; timeouts; optional pinning for high risk. ## Storage & caching Tokens Keychain; URLCache where safe; DTO≠domain; per-endpoint TTL policies. ## Offline mode NWPathMonitor fail-fast OfflineError; writes use feature outboxes—not generic HTTP magic. ## Performance Cancel on disappear; coalesce duplicate GETs; measure p95; HTTP/2. ## Tradeoffs ### Refresh strategy **Option A — Refresh on 401:** Lazy; can stampede without single-flight. **Option B — Proactive refresh:** Fewer mid-flight failures; more refresh traffic. **Pick A when:** With single-flight lock. **Pick B when:** Short-lived tokens with predictable expiry. ### Library vs URLSession **Option A — URLSession:** First-party, enough for most. **Option B — Alamofire/etc:** Faster extras; dependency cost. **Pick A when:** Default modern apps. **Pick B when:** Team already standardized on a lib.
Keep going with AceMobileInterview
Reading helps. Timed practice locks it in. Jump into the interactive track for algorithms with LeetCode links, studio projects, debugging zips, and mobile system design.