Swift
201 bites tagged Swift — interview questions with model answers, and 60-second explainers.
What LLDB command prints a UIView description versus an Int?
Tests LLDB formatting at breakpoints. Great answers: po invokes description or debugDescription on objects, while p evaluates and prints raw primitive values with type info. Red flag: mixing them up or recommending console print instead of LLDB.
Difference between .xcodeproj and .xcworkspace, and when to use a workspace
Tests your mental model of Xcode build containers. A project defines one buildable unit; a workspace groups multiple projects so they build together and share derived data. Use it for package managers or modular codebases.
How does Swift async/await improve on completion handlers?
Tests structured concurrency mastery over callback control flow. A strong answer covers inversion of control, suspension points as yield locations, and Tasks as parent-child units.
Explain Copy-on-Write in Swift and implement it for custom structs
Tests value semantics with reference storage and uniqueness checks. A strong answer explains CoW delays copy until mutation via isKnownUniquelyReferenced, lists custom steps: wrap, read, check, clone. Red flag: assuming structs are automatically CoW.
What is a closure capture list? Explain [weak self] versus [unowned self].
Define capture lists, contrast [weak self] safe optionality against [unowned self] crash risk, and match each to lifetime guarantees. ARC memory safety in Swift closures.
What are Swift generics, why useful, and write a swap function?
This tests parametric polymorphism and type-safe reuse. A strong answer defines generics as placeholder types for reusable code, then writes a swap<T> function using inout parameters. Red flag: confusing generics with Any or omitting inout.
What is a retain cycle in ARC with closures?
It tests reference counting and closure capture semantics. A retain cycle forms when a closure captures self strongly while self holds the closure; break it with weak if self can deallocate, or unowned if it will outlive the closure.
Explain protocols and how extensions provide default implementations
Tests behavior sharing without inheritance. A strong answer defines protocols as requirements, shows extensions injecting default implementations, and contrasts this with base-class inheritance.
Swift struct vs class: differences and when to choose each
Tests value vs reference semantics and let mutability. Strong answers contrast copy behavior with shared references, note allocation tendencies, and choose struct for value semantics or class for identity.
Explain the primary differences between a struct and a class in Swift
Tests value versus reference semantics and their impact on memory and mutation. Strong answers note structs copy on assignment and lack inheritance, while classes share heap instances via ARC. Red flag: claiming structs are always stack-allocated.
What is an optional in Swift? Demonstrate two safe unwrapping methods.
This checks Swift type safety and nil-handling. A strong answer defines Optional as an enum, demonstrates if let binding, and shows the nil-coalescing operator ?? for defaults. Avoid suggesting force-unwrapping with ! as a safe pattern.
What is the difference between let and var in Swift?
This tests value semantics beyond syntax. A strong answer defines let as immutable and var as mutable, notes that let on a reference type only fixes the pointer, and cites clearer intent and compiler optimization.
KVO: Swift's Built-In Observer Pattern
KVO lets an object subscribe to property changes on another object automatically. It shines when you need UI updates driven by model state, but forgetting to remove observers before deallocation crashes your app with an NSException.
Thread Sanitizer catches data races in Swift
Thread Sanitizer turns flaky race crashes into reproducible reports by monitoring memory accesses at runtime. Use it in Xcode to catch unsynchronized cross-thread reads and writes. It only catches races that execute during your test run, so coverage matters.
@objc: Swift's Bridge to Objective-C
@objc is the bridge badge that exposes Swift code to the Objective-C runtime so UIKit selectors and KVO work. You need it for target-action and Core Data. Forget it and you get a runtime crash, not a compiler error.
XCFrameworks: One Bundle for Every Apple Platform
An XCFramework is a shipping container for compiled Apple libraries: one bundle holds device, simulator, and Mac binaries so Xcode picks the right slice automatically. Use it to distribute closed-source SDKs.
XCTestCase: One Fresh Instance Per Test
A XCTestCase subclass is a lab bench for isolated experiments. Each test method is a fresh invocation checked by the runner. The silent killer is shared mutable state on the case: without setUp, tests flake because execution order is never guaranteed.
Custom Rendering with draw(_:)
draw(_:) is the callback where UIKit asks your view for pixels. Override it to render custom shapes or text with Core Graphics when stock views fall short. The footgun is calling it directly or doing non-drawing work inside; use setNeedsDisplay() instead.
withCheckedThrowingContinuation: Bridge Callbacks to Async/Await
withCheckedThrowingContinuation bridges legacy completion-handler APIs into async/await. Wrap one-shot callback-based work so callers use try await instead of nested blocks. The footgun is resuming twice or never, which checked runtimes catch in debug builds.
Unwind Segues: Jump Back in the Stack
An unwind segue jumps from a deep screen to an earlier view controller without manual popping. Use it after multi-step flows to return to a root screen. If multiple screens share the same action, UIKit picks the nearest one and silently routes users wrong.
Map Data to Views Using navigationDestination
navigationDestination turns NavigationStack into a router: register a view per data type, then push raw values. It frees view models from creating views. Using it outside NavigationStack or mixing it with old NavigationLink destinations silently breaks…
Build Custom Instruments with os_signpost
os_signpost turns code intervals into Instruments graphs by pairing begin-end markers with a visualization package. Use it to correlate app work like model hydration with system CPU and memory metrics. Unmatched begin-end calls break tracks and ruin the view.
Swift Existential Types: The Polymorphism Box
An existential type is a boxed protocol: you see the interface, not the concrete type inside. Use it to store mixed concrete types behind one protocol, like [any Logger]. Prefer generics; existentials hide types and add dynamic dispatch overhead.
Protocol-Oriented Programming in Swift
Protocol-oriented programming swaps inheritance for composable capabilities via protocol extensions. Use it to share behavior across structs without forcing a superclass. The footgun is protocol bloat: indirection without reuse is bureaucracy.
Get Swift bites daily.
Five a day, five minutes, offline. With quizzes so it sticks.
Open testing — you’ll join as an early tester.