Overview › Dependency Injection
Dependency Injection
Native init-based DI, no formal framework; brittle for testing at scale.
60
SCORE
Summary
iOS does not use a formal DI framework (no Swinject, Resolver, Factory). Dependencies are passed through initializers and feature ViewModels accept their collaborators as init parameters. This is fine for small modules but makes test setup verbose for ViewModels with many dependencies.
How DI is currently done
| Layer | Mechanism | Notes |
|---|---|---|
| Feature ViewModels | Initializer injection of protocols defined in Core | Tests substitute Mockey-generated mocks or hand-written fakes |
| Network client | Singleton-style instance configured in CoreImplementation | Acceptable for a service with no per-screen state |
| Storage | Protocol-based; concrete instance from Storage SPM | Clean |
| Composition root | Spread across feature flow controllers | No central composition |
| SwiftUI environment | Limited use of @Environment for cross-cutting deps | Opportunity |
Recommended pattern
For a codebase this size, a lightweight Factory registry (similar to the Hmlongco/Factory library) gives you:
- Centralized declaration of dependencies in one file per package.
- Auto-resolution into ViewModels via
@Injectedor initializer. - Easy test-time substitution via
register. - Compile-time visibility into the dependency graph.
Alternative: stay with manual initializer DI but introduce one Composer per feature that owns the wiring.
Findings
""PASS
Init-based DI is explicit and Swift-idiomatic
No magic; every dependency is visible at the call site.
MEDIUM
Verbose test setup in ViewModels with many deps
NewOnboardingViewModelTest equivalent — when a ViewModel has 30+ collaborators, every test sets up 30+ mocks.Recommendation: Extract collaborators into use cases; ViewModel tests then mock 1-3 use cases.
MEDIUM
No central composition root
Object graph wiring is spread across the app — adding a new dependency requires touching multiple files.
Recommendation: Adopt a lightweight Factory pattern (e.g. Hmlongco's Factory library) or build a small Composer at the app boundary.
LOWSwiftUI
SwiftUI @Environment as pseudo-DI
For SwiftUI views,
@Environment is a low-friction DI mechanism for cross-cutting deps.Recommendation: Define
EnvironmentValues entries for analytics, theming, feature flags.No findings logged in this category yet for iOS.
Costco iOS · Code Review Report · Generated 2026-05-07 · 88 machine-curated findings