iOS knowledge interviews
In this round the interviewer asks about Swift and the iOS platform. It sounds easy: "just questions". But the follow-up questions go deep fast. Memorised definitions are not enough.
How the round works
There are two common styles.
1. Rapid questions. Many short questions on different topics.
"What is the difference between a struct and a class?" "What does
@escapingmean?" "What is@MainActor?"
2. Deep dive. One topic, deeper and deeper.
"What is ARC?" → "What is a retain cycle?" → "Show me one in code." → "How do you find one in a real app?"
Many interviewers also ask about your resume: "You wrote that you used Core Data. Why Core Data and not SwiftData?"
The answer formula: definition → example → trade-off
Use three parts for every answer. It is short, clear, and shows real experience.
- Definition: one or two sentences. What is it?
- Example: a small piece of code or a real case from your work.
- Trade-off: when you would use it, when not, or what it costs.
Aim for 1–2 minutes. Then stop and let the interviewer ask more.
Example 1: "What is the difference between a struct and a class?"
Definition:
"A struct is a value type. When you assign it, you get a copy. A class is a reference type. When you assign it, both variables point to the same object."
Example:
struct PointS { var x = 0 }
final class PointC { var x = 0 }
var a = PointS()
var b = a
b.x = 5
print(a.x) // 0, a is a separate copy
let c = PointC()
let d = c
d.x = 5
print(c.x) // 5, same objectTrade-off:
"I use structs by default for models, because copies make code easier to reason about and are safer with concurrency. I use a class when I need shared identity, like a view model or a cache, or when I need inheritance or deinit."
Example 2: "When do you use weak vs unowned?"
Definition:
"Both break retain cycles.
weakbecomesnilwhen the object is freed, so it is always optional.unownedis not optional and assumes the object is still alive."
Example:
final class PlayerViewController: UIViewController {
private let player = VideoPlayer()
override func viewDidLoad() {
super.viewDidLoad()
player.onFinish = { [weak self] in
self?.showReplayButton()
}
}
private func showReplayButton() { /* ... */ }
}Trade-off:
"
unownedcrashes if the object is gone. So I useweakin almost all closures. I useunownedonly when the other object always lives longer, for example a child that cannot exist without its parent."
Example 3: "What is an actor?"
Definition:
"An actor is a reference type that protects its mutable state. Only one task can run code inside the actor at a time, so there are no data races."
Example:
actor ImageCache {
private var images: [URL: Data] = [:]
func image(for url: URL) -> Data? { images[url] }
func store(_ data: Data, for url: URL) { images[url] = data }
}
// From outside, calls need await
let data = await cache.image(for: url)Trade-off:
"Actors make thread safety simple. The cost is that every call from outside is
async. Also, actors are reentrant: when the actor awaits something, other calls can run in between, so state can change across anawait. I check state again after eachawait."
The reentrancy point is a strong signal. Many candidates miss it.
What makes an answer weak
| Weak | Why | Better |
|---|---|---|
| "GCD is for threads." | Too short, no detail | Say what queues are, show DispatchQueue.main.async, compare with async/await. |
| A 5-minute speech | The interviewer cannot steer | Stop after 1–2 minutes. |
| Only theory | No proof of experience | Add "In my last project, I…". |
| Guessing with confidence | Wrong answers hurt trust | Say "I am not sure, but I think…" and reason. |
| "Always use X" | No nuance | Say when you would not use X. |
How to handle "I don't know"
You will not know everything. Nobody does. Use this pattern:
- Be honest.
- Say what you do know that is close.
- Reason out loud.
"I have not used
NSCachein production. I know it is a key-value cache that can remove items when memory is low. So I would use it for images. I would check whether it copies the keys, likeNSDictionarydoes."
This is much better than a wrong guess or silence.
Show experience, not just knowledge
Interviewers want to know if you have done the work. Small real details help a lot.
- "I found this retain cycle with the Memory Graph Debugger in Xcode."
- "We saw this crash in our crash reports only on older devices."
- "Thread Sanitizer showed a data race in our analytics code."
- "Instruments showed 40% of launch time was in one SDK setup call."
If you have no production experience with a topic, say what you built to learn it.
Top topics checklist
Use this list to find gaps. For each item, can you give a definition, an example and a trade-off?
Swift language
- Value vs reference types, copy-on-write
- Optionals,
if let,guard let, optional chaining - Protocols, protocol extensions, default implementations
- Generics, associated types,
somevsany - Closures,
@escaping, capture lists - Enums with associated values
- Error handling:
throws,Result, typed throws - Access control:
private,fileprivate,internal,public,open - Property wrappers and macros (what they do, not how to write them)
Memory
- ARC and reference counting
- Retain cycles in closures, delegates, timers
-
weakvsunowned - Finding leaks: Memory Graph Debugger, Instruments
Concurrency
- GCD: main queue, global queues, serial vs concurrent
-
async/await,Task, task cancellation - Structured concurrency:
async let, task groups - Actors, actor reentrancy,
@MainActor -
Sendableand Swift 6 strict concurrency checking - Data races and how to find them (Thread Sanitizer)
UIKit
- View controller lifecycle (
viewDidLoad,viewWillAppear, and so on) - Auto Layout, intrinsic content size, content hugging and compression resistance
- Table and collection views, cell reuse, diffable data sources
- Delegation and the responder chain
SwiftUI
-
@State,@Binding,@Environment,@Observable - View identity and why it matters (
id,ForEach) - When the body is re-evaluated
-
.taskvs.onAppear - Mixing SwiftUI and UIKit (
UIHostingController,UIViewRepresentable)
Architecture
- MVC, MVVM, and one more (for example TCA, VIPER or Clean)
- Dependency injection with protocols
- Navigation: coordinators,
NavigationStack - Modularisation with Swift packages
Networking and data
-
URLSession,Codable, error handling - Caching (HTTP cache, in-memory, disk)
- Persistence options:
UserDefaults, Keychain, files, Core Data, SwiftData - Pagination and offline support
App and platform
- App lifecycle and scene lifecycle
- Background tasks, push notifications
- Security: Keychain, App Transport Security, certificate pinning
- Accessibility: VoiceOver, Dynamic Type
- Performance: launch time, scroll performance, main thread work
Testing and tooling
- XCTest and Swift Testing (
@Test,#expect) - Mocks and fakes with protocols
- UI tests, snapshot tests
- Swift Package Manager, build configurations, CI
Common follow-up questions to expect
Prepare for these. They test depth.
- "Why is
@MainActorneeded if you already useDispatchQueue.main?" - "What happens if you capture
selfstrongly in aTask?" - "How does SwiftUI know when to redraw a view?"
- "What is the difference between
some Viewandany View?" - "How would you store a user's auth token? Why not
UserDefaults?" - "Why are cells reused, and what bug can that cause?"
Example short answer for the last one:
"Cells are reused to save memory and keep scrolling smooth. The common bug is old content showing in a reused cell, for example the wrong image after a slow download. I reset the cell in
prepareForReuse()and check that the result still matches the cell's item before I set the image."
override func prepareForReuse() {
super.prepareForReuse()
imageTask?.cancel()
imageView.image = nil
}How to practise
- Use the quiz questions on this site. Read the title, then answer out loud before you open the answer.
- Time yourself: 1–2 minutes per answer.
- After each answer, check: did I give a definition, an example and a trade-off?
- Start with "high" importance questions. They come up most often.
- Write every question you could not answer in your mistakes list. Return to it in a week.