Swift Case Studies & Practical Application 5 — Questions and Answers
Question 1: You're building a feature flag system. Flags are checked thousands of times per second. A dictionary-backed solution with `String` keys works but a colleague proposes using an enum. What is the runtime advantage?
- Enums use less memory than Strings on the heap
- Enum cases are compared as integers, making switch exhaustive and O(1) with no hashing (Correct answer)
- Enums automatically cache their associated values
- String keys are O(n) in dictionaries
Correct answer: Enum cases are compared as integers, making switch exhaustive and O(1) with no hashing
Switching on an enum compiles to an integer comparison or jump table, which is faster and exhaustively checked by the compiler, unlike string-keyed dictionary lookups.
Question 2: A `RecipeParser` must support JSON, XML, and CSV formats. You want to add new formats without modifying the parser. Which design embodies the Open/Closed Principle in Swift?
- Add a format parameter to every method and expand the switch statement
- Define a `FormatParser` protocol; create `JSONParser`, `XMLParser`, `CSVParser` conformances injected at runtime (Correct answer)
- Use a global `formatType` variable checked inside the parser
- Subclass `RecipeParser` for each format
Correct answer: Define a `FormatParser` protocol; create `JSONParser`, `XMLParser`, `CSVParser` conformances injected at runtime
Protocol-based strategy injection lets you add `YAMLParser` later by writing a new conformance, leaving `RecipeParser` itself unchanged — open for extension, closed for modification.
Question 3: Your app's test suite uses real `URLSession` calls and intermittently fails due to network conditions. What is the most effective fix without rewriting the production API layer?
- Add `sleep(2)` before each network assertion
- Introduce a `URLProtocol` subclass that intercepts requests and returns canned responses (Correct answer)
- Switch all tests to integration tests running against a live server
- Mark flaky tests with `XCTSkip`
Correct answer: Introduce a `URLProtocol` subclass that intercepts requests and returns canned responses
A custom `URLProtocol` subclass registered with the test session intercepts all URLSession requests at the protocol level, returning deterministic mock responses without changing production code.
Question 4: You profile an app with Instruments and find a hot path allocates a new `TransformMatrix` struct on every animation frame. What optimization should you investigate first?
- Convert `TransformMatrix` to a class to use reference semantics
- Cache or reuse the struct across frames rather than reallocating each time (Correct answer)
- Add `@inlinable` to all TransformMatrix methods
- Use `UnsafePointer` to avoid Swift overhead
Correct answer: Cache or reuse the struct across frames rather than reallocating each time
Avoiding per-frame allocation by caching the struct (or using a pre-allocated buffer) reduces memory pressure and eliminates the initialization cost on the hot path.
Question 5: A Swift property wrapper `@Clamped(range: 0...100)` should constrain any `Int` to the given range on set. Which stored property inside the wrapper holds the backing value?
- `wrappedValue` with a setter that clamps before storing to a private variable (Correct answer)
- `projectedValue` accessed via the `$` prefix
- `rawValue` like a RawRepresentable type
- `storedValue` as a special keyword
Correct answer: `wrappedValue` with a setter that clamps before storing to a private variable
Property wrappers use `wrappedValue` as the primary interface; a custom setter there can clamp the incoming value before assigning it to a private backing store.
Question 6: You need to conditionally include debug-only diagnostic code in a Swift framework without any runtime cost in release builds. Which tool achieves this?
- A runtime `if ProcessInfo.processInfo.environment["DEBUG"] != nil` check
- Wrapping code in `#if DEBUG ... #endif` compiler directives (Correct answer)
- Using a `@discardableResult` attribute on debug functions
- Setting a global `isDebug: Bool` constant
Correct answer: Wrapping code in `#if DEBUG ... #endif` compiler directives
`#if DEBUG` is a compile-time conditional: the enclosed code is completely stripped from release builds, adding zero binary size or runtime cost.
Question 7: A `StreamProcessor` conforms to `AsyncSequence` and yields values over time. A view controller consumes it with `for await value in stream`. What happens to the loop when the view controller is deallocated?
- The loop continues running in the background indefinitely
- If the `Task` running the loop is cancelled (e.g., in `deinit`), the loop exits at the next `await` suspension point (Correct answer)
- Swift automatically cancels async loops when the caller is released
- The loop throws a `DeallocationError`
Correct answer: If the `Task` running the loop is cancelled (e.g., in `deinit`), the loop exits at the next `await` suspension point
Structured concurrency requires explicit cancellation; storing the `Task` and calling `.cancel()` in `deinit` causes the `for await` loop to exit cleanly at its next suspension point.
You're building a feature flag system.
Flags are checked thousands of times per second.
A dictionary-backed solution with `String` keys works but a colleague proposes using an enum.
What is the runtime advantage?