Architecture & Tooling
Writing Swift that compiles is one skill; structuring, testing, and shipping an app that a whole team can keep changing for years is another — and it is the one senior iOS interviews probe hardest. Nobody senior is asked to define an optional, but everyone is asked why the view controller grew to 1,500 lines, where business logic should live, and what happens between a green build and a user's phone. The recurring theme here is judgement: there is rarely one correct architecture or test strategy, only trade-offs you can state and defend.
This topic covers the three concerns that decide an app's long-term health. First, architecture — the presentation patterns (MVC, MVVM, MVP, VIPER, Clean) and the plumbing around them (dependency injection, coordinators, unidirectional flow) that keep business logic out of the view layer and make the code testable. Second, testing — the pyramid of unit, integration, and UI tests, the test doubles that isolate a unit, and the async and coverage traps that make suites lie. Third, tooling and release — the build system, dependency managers, the code-signing maze, and the pipeline that turns a commit into a TestFlight build and then an App Store version you can roll back.
Topic map
- Architecture patterns — MVC and the massive view controller, MVVM and bindings, VIPER and Clean, dependency injection, coordinators, and where business logic belongs.
- Testing — the test pyramid, XCTest and Swift Testing, mocking through protocols, async and snapshot testing, and why line coverage is a gap-finder, not a target.
- Tooling & release — the Xcode build system, SPM vs CocoaPods vs Carthage, code signing and provisioning, TestFlight and phased release, CI, and crash symbolication.
Common traps
| Mistake | Consequence |
|---|---|
| Putting networking and persistence in the view controller | A massive, untestable controller that mixes four responsibilities |
| Letting the view model import UIKit or SwiftUI | Presentation logic becomes untestable and coupled to the framework |
| Treating "more coverage" as the goal | 85% coverage with lines that run but assert nothing, and bugs still ship |
Calling URLSession.shared directly inside the type under test | No seam to inject a fake, so every test hits the network |
| Confusing a certificate, App ID, entitlement, and provisioning profile | Signing fails on CI with an error nobody on the team can decode |
| Expecting automatic signing to work on a clean CI machine | The build fails on a missing profile the developer's Mac quietly had |
Interview relevance
This is the senior filter. A junior can pass by defining MVVM; a senior is expected to choose it over VIPER for a 30-engineer team and name the trade-off — less structure for less onboarding cost. The strongest answers treat architecture, tests, and release as one system: business logic pulled into testable types, a pyramid that keeps fast tests plentiful and slow UI tests few, and a pipeline that can stop a bad build with a kill switch before it reaches most users. Reciting patterns reads as junior; reasoning about the trade-off you are knowingly accepting reads as the person who has shipped and maintained real apps.