Fifteen common Swift interview questions
- What are optionals, and how do you unwrap them safely?
- if let versus guard let?
- Struct versus class — when to use each?
- What does copy-on-write mean?
- How does ARC work?
- What is a retain cycle, and how do weak and unowned help?
- What are capture lists in closures?
- Escaping versus non-escaping closures?
- What is protocol-oriented programming?
- What are associated types and generics?
- How does Swift error handling work?
- What are async/await and structured concurrency?
- What are actors, and what problem do they solve?
- What is @MainActor?
- What are property wrappers?
Optionals and types
- Optionals represent a value or nil; unwrap with if let, guard let, nil-coalescing (??) or optional chaining (?.). Force unwrapping (!) crashes on nil.
- guard let exits early and keeps the unwrapped value in scope afterwards; if let scopes it to the block.
- Structs are value types — copied on assignment — making them safer for data models and thread-friendly. Classes are reference types with identity and inheritance.
- Copy-on-write: standard collections share storage until one copy is mutated, so value semantics stay cheap.
Memory management
Automatic Reference Counting frees a class instance when no strong references remain. Retain cycles occur when two objects hold strong references to each other — commonly a view controller and a closure it stores that captures self. Break them with weak references (optional, become nil when the object is freed) or unowned references (non-optional, for when the other object is guaranteed to outlive the reference). In closures, use a capture list such as [weak self] and unwrap self inside.
Protocols, generics and closures
| Concept | Answer |
|---|---|
| Protocol-oriented programming | Model behaviour with protocols and extensions instead of class inheritance |
| Protocol extensions | Provide default implementations to conforming types |
| Associated types | Placeholders in protocols, filled by each conforming type |
| Generics with constraints | Reusable code over types meeting requirements, such as T: Comparable |
| some vs any | Opaque type with one concrete type hidden vs existential box allowing any conforming type |
| @escaping | The closure may outlive the function call, such as completion handlers stored for later |
Errors and concurrency
Functions that can fail are marked throws and called with try inside do–catch, or with try? to convert errors to nil. Swift concurrency uses async functions and await for suspension points, with structured concurrency via async let and task groups so child tasks are cancelled with their parent. Actors protect mutable state by allowing only one task at a time to access their isolated properties, preventing data races. @MainActor ensures code runs on the main thread, which UI updates require. Swift 6's strict concurrency checking turns many data-race risks into compile-time errors.
Property wrappers and SwiftUI
Property wrappers encapsulate storage logic, such as @State and @Binding in SwiftUI or @AppStorage for user defaults. Expect SwiftUI questions about view identity, state ownership (@State versus @StateObject versus @ObservedObject, or the Observation framework's @Observable) and why views should be lightweight. See iOS interview questions.
A code question to rehearse
A view controller stores a closure that refers to self, and the controller is never deallocated. Explain the retain cycle — the controller holds the closure strongly and the closure holds the controller — and fix it with a capture list such as [weak self], unwrapping self inside with guard let. Then mention how you'd confirm the fix: a deinit log or the memory graph debugger in Xcode.
Practising
Reading answers is not the same as saying them. Pick ten of the questions above and answer them aloud against a timer; a free AI interview assistant like CoPilot Interview can ask Swift questions in a mock interview and flag answers that ran long or lacked an example. Prepare to spot a retain cycle in a closure snippet and fix it — it's one of the most common code questions.
Disclosure: CoPilot Interview is our product, so weigh what we say about it accordingly. Everything else on this page applies whichever tool you use, or none.
Frequently asked questions
What are common Swift interview questions?
Optionals and unwrapping, structs versus classes, copy-on-write, ARC and retain cycles, weak versus unowned, closures and capture lists, protocols and generics, error handling, async/await, actors and property wrappers.
Struct or class in Swift?
Prefer structs for data models because value semantics avoid shared mutable state. Use classes when you need identity, inheritance or reference semantics, such as shared controllers.
How do you avoid retain cycles in Swift?
Use weak or unowned references for back-references and capture lists such as [weak self] in closures that the object stores.
What is an actor in Swift?
A reference type that protects its mutable state by allowing only one task at a time to access it, preventing data races in concurrent code.
Practise on real interview questions
Run 145 real interview questions across 10 tracks, answer out loud and see a structured answer to compare with yours. Free, no signup.
Try a practice question