Introduction: Why Swift is the Key to a Successful Interview
A Swift interview is not just a syntax check. The Apple ecosystem requires an understanding of the language's fundamental principles, memory management, and modern frameworks. In this article, we will break down the top questions you will definitely be asked at any level — from Junior to Senior. You will learn not only the correct answers but also the typical pitfalls candidates fall into.
The article is written for the educational portal PythonLib but is adapted for Swift. We have structured the material so you can quickly review key topics before your interview.
1. Swift Basics: Optional, Value vs Reference Types
What is an Optional and why is it needed?
An Optional is an enum that can be either .none (nil) or .some(Wrapped). It is Swift's way of safely handling the absence of a value.
var name: String? = "Alice"var age: Int? = nil
// Safe unwrappingif let unwrappedName = name { print("Hello, \\(unwrappedName)")} else { print("Name is nil")}Common mistake: Using force unwrap (!) without checking. Always prefer guard let or if let.
Value Types vs Reference Types
Swift strictly separates types:
- Value Types (structs, enums, basic types) — copied on assignment.
- Reference Types (classes) — passed by reference.
struct Point { var x: Int var y: Int}
class Car { var model: String init(model: String) { self.model = model }}
var point1 = Point(x: 1, y: 2)var point2 = point1point2.x = 5 // point1.x remains 1
var car1 = Car(model: "Tesla")var car2 = car1car2.model = "BMW" // car1.model also becomes "BMW"Interview question: "Why does Apple recommend using structs instead of classes?" Answer: thread safety, predictability, no ARC overhead.
2. Memory Management and ARC: How to Avoid Leaks
How does Automatic Reference Counting (ARC) work?
ARC automatically counts references to class objects. When the count reaches zero, memory is freed. Problems arise with cyclic references.
class Person { let name: String var apartment: Apartment? init(name: String) { self.name = name } deinit { print("\\(name) deallocated") }}
class Apartment { let unit: String weak var tenant: Person? // weak — weak reference init(unit: String) { self.unit = unit } deinit { print("Apartment \\(unit) deallocated") }}
var john: Person? = Person(name: "John")var unit4A: Apartment? = Apartment(unit: "4A")john?.apartment = unit4Aunit4A?.tenant = johnjohn = nilunit4A = nil// Both objects will be deallocatedKey modifiers:
weak— always optional, automatically becomes nil upon deallocation.unowned— non-optional, assumes the object is alive (risk of crash).
Typical question: "What is the difference between weak and unowned?" Answer: weak is safer, unowned is more convenient for mandatory dependencies (e.g., delegate).
3. Frameworks: UIKit vs SwiftUI, GCD and Protocols
UIKit: ViewController Lifecycle and Delegate Pattern
Understanding viewDidLoad, viewWillAppear, viewDidDisappear is basic. But in interviews, they often ask about the Delegate pattern:
protocol MyDelegate: AnyObject { func didTapButton()}
class MyView: UIView { weak var delegate: MyDelegate? @objc func buttonTapped() { delegate?.didTapButton() }}
class MyViewControlle