Discover Dependency Injection
You’re more of a video kind of person? I’ve got you covered! Here’s a video with the same content than this article 🍿
Dependency Injection can feel a bit mysterious when you’ve never used it 😶🌫️
But I swear it’s really easy to understand! 😌
In just a few paragraphs we’ll go over everything you need to figure out how this pattern works!
Let’s start with this ViewModel:
This ViewModel has a dependency of type Service.
And we can notice that, for now, the ViewModel is responsible for both creating and using its Service 🤨
But this is not very flexible, because it makes it difficult to change the way our ViewModel is configured 😰
That’s why it would make sense to be able to inject the dependency Service inside the ViewModel!
So let’s do it in 5 easy steps 🚀
Step 1️⃣, we create a protocol with the API of the Service:
Step 2️⃣, we hide the implementation of our Service behind that protocol:
Step 3️⃣, we implement an initializer for the ViewModel:
Step 4️⃣, we can now use this initializer to inject the Service in the ViewModel:
Step 5️⃣, if needed we can now also inject a mocked implementation of the Service:
And that’s it, we’ve successfully implemented a simple version of Dependency Injection 🥳
Here’s the code if you want to experiment with it!
protocol Servicing {
func fetchData(_ completion: @escaping (Int) -> Void)
}
class Service: Servicing {
func fetchData(_ completion: @escaping (Int) -> Void) {
/* ... */
}
}
class ViewModel: ObservableObject {
@Published var data: Int?
let service: Servicing
init(service: Servicing) {
self.service = service
}
func fetchData() {
service.fetchData { [weak self] data in
self?.data = data
}
}
}
class MockedService: Servicing {
func fetchData(_ completion: @escaping (Int) -> Void) {
// Mocked Implementation
DispatchQueue.main.async {
let randomData = Int.random(in: 0...100)
completion(randomData)
}
}
}
let viewModel = ViewModel(service: MockedService())