Dependency Injection in Swift: Stop Creating, Start Receiving

Dependency Injection means objects receive their dependencies from the outside rather than creating them internally. It's used to give a view model a network client or data source, making it testable.
Why it exists
Dependency Injection exists to break up tightly coupled code. When an object creates its own dependencies, like let service = RealNetworkService(), it's permanently tied to that specific implementation. This makes the object difficult to test in isolation or reuse with a different service.
The mental model
Think of a chef in a restaurant. The chef doesn't grow their own vegetables or raise their own cattle. Instead, ingredients (dependencies) are delivered to the kitchen (injected). This lets the chef focus on cooking (the object's logic) and allows the restaurant owner to swap suppliers (different dependency implementations) without changing the chef's recipes.
How it works
The most common form in Swift is Initializer Injection. An object declares its dependencies as properties and receives concrete instances through its init method. To maximize flexibility, the dependency is usually defined as a protocol, not a concrete class. The object creating the instance is responsible for providing the dependency, decoupling the receiver from knowing how to build it.
When to use it
Use DI to provide external services like network clients, data sources, or analytics trackers to your objects, especially view models. It is fundamental for unit testing. By injecting a mock dependency (e.g., a MockDataProvider that returns canned data), you can test an object's logic in isolation without hitting a real network or database.
When not to use it
Simple initializer injection can become clumsy in deep SwiftUI view hierarchies. If a child view deep in the navigation stack needs a dependency, every parent view above it may have to accept and pass down that dependency, even if they don't use it. This problem, sometimes called "dependency threading," clutters initializers and can signal the need for a more advanced DI container or environment-based approach.
One canonical example
A UserProfileViewModel needs to fetch data. Instead of creating a data source itself, it asks for one that conforms to a protocol.
protocol DataProviding {
func retrieveUserData() -> UserData
}
class UserProfileViewModel {let dataProvider: DataProviding
init(dataProvider: DataProviding) {self.dataProvider = dataProvider } }
This allows you to initialize it with a RealDataProvider in your app or a MockDataProvider in your tests.
Interview question
What is the main benefit of using Dependency Injection in Swift applications?
- a.It guarantees that only one instance of a shared resource exists throughout the application lifecycle.
- b.It allows objects to be tested independently by providing flexible ways to swap out their external dependencies.Correct
- c.It automatically manages the instantiation and destruction of all service objects.
- d.It simplifies the process of passing data between deeply nested views in a SwiftUI hierarchy.
Why? this is the answer
The card explicitly states that Dependency Injection exists to break up tightly coupled code, making objects testable in isolation by allowing mock dependencies to be injected. Option B directly reflects this core purpose. Option D is a tempting distractor, but the card notes that simple initializer injection can actually complicate dependency passing in deep SwiftUI hierarchies, not simplify it.
Just read this? Test yourself on what you have been reading.
Read the original → donnywals.com
You just looked this up. Could you explain it out loud?
That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on swift — each one lists the topics its interview covers.
See open roles