Swift Language
Swift is a value-first, compile-time-safe language, and this is where almost every iOS interview starts — not with UIKit or SwiftUI, but with the language model underneath them. The recurring theme is that Swift converts whole classes of bug into compile errors. An optional turns "this might be missing" into a type the compiler forces you to handle, so the null-pointer crash simply cannot compile. A struct's value semantics mean assigning it copies it, so two variables never accidentally alias the same mutable state. A generic constraint lets the compiler prove a method exists before the code ships. The engineer who internalises this stops fighting the compiler and starts letting it carry the weight.
This topic walks the language from the ground up. We begin with the everyday tools — optionals, let versus var, enums with associated values, pattern matching — then the single most-tested distinction: value versus reference types, and the copy-on-write that keeps copying cheap. From there we cover closures and the capture traps that leak memory, the protocol-and-generics system that replaces class inheritance, error handling across throws / Result / optionals, and finally property wrappers and macros — the compile-time code generation behind @State and @Observable.
Topic map
- Swift basics — optionals and safe unwrapping,
letvsvar, type inference, enums with associated values, pattern matching, andguard/if let. - Value & reference types — struct copies vs class sharing, copy-on-write, identity vs equality, mutation semantics, and the "structs are always cheap to copy" myth.
- Closures & functions — capture semantics and capture lists,
[weak self]/[unowned self], escaping vs non-escaping, higher-order functions, and@autoclosure. - Protocols & generics — protocol-oriented design, associated types and witness tables, generic constraints,
somevsany, and default implementations. - Error handling —
throws/try/catch, thetryvariants,Result,rethrows,defer, and when to pick optionals vs throwing vsResult. - Property wrappers & macros — what a wrapper compiles to,
wrappedValue/projectedValue, and how a Swift macro like@Observablediffers from a wrapper.
Common traps
| Mistake | Consequence |
|---|---|
Force-unwrapping ! as the default way to read an optional | A nil crash reaches production instead of being handled |
Treating a struct like a class (or vice versa) | Wrong copy vs share behaviour; aliasing bugs or lost mutations |
Assuming a struct copy is always O(1) | A copy-on-write buffer or many stored fields makes it O(n) on first write |
Capturing self strongly in an escaping closure | A retain cycle leaks the view controller |
| Adding a method only in a protocol extension and expecting override | Static dispatch runs the extension version through any P |
Reaching for try! or ignoring an error | A recoverable failure becomes a crash |
Interview relevance
The language round is a filter: it separates candidates who understand why Swift behaves as it does from those who have memorised syntax. Saying "a struct is copied on assignment, so mutating one never affects the other, and copy-on-write keeps that cheap until the first write" instantly reads as senior. The strongest answers connect the guarantee to the mechanism — optionals to compile-time nil checking, [weak self] to ARC and retain cycles, some vs any to static versus dynamic dispatch — rather than reciting a definition.