Swift Case Studies & Practical Application 2 — Questions and Answers
Question 1: You're building a banking app where a `Transaction` must always have a non-zero `amount`. Which Swift feature best enforces this at the type level?
- A guard statement at call sites
- A failable initializer that returns nil for zero amounts (Correct answer)
- An optional property with a didSet observer
- A global validation function called before use
Correct answer: A failable initializer that returns nil for zero amounts
A failable initializer (`init?`) prevents creating an invalid `Transaction` by returning nil when the amount is zero, enforcing the invariant at construction time.
Question 2: A networking layer returns `Data?` from a cache. You need to decode it as `User` or fall back to fetching from the server. Which pattern is most idiomatic in Swift?
- Force-unwrap the optional and catch any crashes
- Use `if let data = cachedData, let user = try? JSONDecoder().decode(User.self, from: data)` (Correct answer)
- Wrap everything in a do-catch and throw if nil
- Use `guard` with a forced cast to Data
Correct answer: Use `if let data = cachedData, let user = try? JSONDecoder().decode(User.self, from: data)`
`if let` chaining safely unwraps the optional data and attempts decoding without crashing or leaking errors into the call site.
Question 3: Your app stores user settings with keys like `"theme"`, `"fontSize"`, etc. A teammate suggests using an enum with raw values instead of string literals. What is the primary benefit?
- Enums are stored faster in UserDefaults than strings
- Compile-time safety prevents typos in key names (Correct answer)
- Enums automatically conform to Codable
- String raw values are deprecated in Swift 5
Correct answer: Compile-time safety prevents typos in key names
Enum cases with String raw values let the compiler catch misspelled key names, eliminating a class of runtime bugs common with bare string literals.
Question 4: You have a `Document` class with an expensive `parse()` method. Many view controllers read `parsedContent` but parsing should happen only once. Which Swift pattern solves this?
- A `lazy var` computed property that caches the result after first access (Correct answer)
- A global variable initialized at app launch
- A `@Published` property that triggers on every set
- A weak reference to a shared cache object
Correct answer: A `lazy var` computed property that caches the result after first access
`lazy var` defers the expensive computation until first access and then stores the result, so subsequent reads are instant without manual caching logic.
Question 5: A social media feed loads posts asynchronously. Which Swift concurrency construct lets you kick off loading user data and post images simultaneously, then wait for both before rendering?
- Two sequential `await` calls inside a Task
- Using `async let` for both fetches then awaiting them together (Correct answer)
- DispatchGroup with two async blocks
- A single `TaskGroup` with one child task
Correct answer: Using `async let` for both fetches then awaiting them together
`async let` starts both async operations concurrently and the subsequent `await` on both ensures neither renders until both complete.
Question 6: You need a `Stack<T>` collection that works with any type and exposes `push`, `pop`, and `peek`. What is the correct Swift approach?
- A class with an Any array property
- A generic struct with a private Array<T> backing store (Correct answer)
- An enum with associated values for each element
- A protocol with a Self requirement
Correct answer: A generic struct with a private Array<T> backing store
A generic struct `Stack<T>` with a private `[T]` backing store is idiomatic Swift: value semantics, type-safe, and zero boxing overhead.
Question 7: A `UITableView` delegate method calls a closure stored in a cell's view model. The closure captures `self` (the view controller). What memory issue can arise and how do you fix it?
- Stack overflow from recursive closures; use `@escaping`
- A retain cycle keeping the view controller alive; capture `self` as `weak` or `unowned` (Correct answer)
- A dangling pointer because closures are value types
- Thread safety issues; dispatch to the main queue
Correct answer: A retain cycle keeping the view controller alive; capture `self` as `weak` or `unowned`
If the view model's closure strongly captures the view controller, and the view controller owns the view model, a retain cycle forms — breaking it requires `[weak self]` or `[unowned self]`.
You're building a banking app where a `Transaction` must always have a non-zero `amount`.
Which Swift feature best enforces this at the type level?