Factory is the Dependency Injection (DI) library which will replace it’s popular predecessor – Resolver.
Factory continues to be very lightweight, with just 1 file and 400+ LOC. That makes me less afraid of integrating it into my projects.
How to setup a container?
Firstly, you will simply extend Container
and add your dependencies, such as services.
extension Container {
static let serviceA = Factory(scope: .singleton) { ServiceA() }
static let serviceB = Factory(scope: .singleton) { ServiceB() }
}
It is important to use singleton
as the scope if you want 1 instance for the whole lifetime.
The default scope is unique
, whereby the factory will create a new instance every time. Unknowingly, this can be a PITFALL. This is usually not the behaviour we want, so do use singleton
, or shared
or a custom Cached session.
MVVM & SwiftUI
We will have a View holding a ViewModel, typical of a MVVM.
struct BookView: View {
@StateObject var model = BookViewModel()
}
The ViewModel will be using a service from the container. There are 2 ways.
class BookViewModel: ObservableObject {
// 1. Using @Injected from Factory
@Injected(Container.serviceA) private var serviceA
// 2. Using a Service Locator Pattern
private let serviceA = Container.serviceA()
}
Mock it in preview
Whenever you need to mock the dependencies, especially for SwiftUI preview, you can register a mock service.
struct BookView_Previews: PreviewProvider {
static var previews: some View {
let _ = Container.serviceA.register { MockServiceA() }
BookView()
}
}
Inject an optional object
It is common to pass a User
object, if the user has been authenticated, else nil.
extension Container {
static let userProviding = Factory<UserProviding?> { nil }
}
// Set when authenticated
Container.userProviding.register { UserProvider(user: user) }
// Reset when logged out
Container.userProviding.reset()
The injected Container.userProviding
will be an optional type.
And more
There are other features such as constructing parameters, @LazyInjected and @WeakLazyInjected and custom containers.