DIContainer Swift
It is an ultra-light dependency injection container made to help developers to handle dependencies easily.
We know that handle with dependency injection is hard and generates boilerplate code a lot.
The main idea of this lib is to keep it simples and light, it should be direct and intuitive, even using the property wrapper.
What is Dependency Injection?
The intent behind dependency injection is to achieve separation of concerns of construction and use of objects. This can increase readability and code reuse.
Dependency injection is one form of the broader technique of inversion of control. A client who wants to call some services should not have to know how to construct those services. Instead, the client delegates to external code (the injector). The client is not aware of the injector.[2] The injector passes the services, which might exist or be constructed by the injector itself, to the client. The client then uses the services.
Font - Wikipedia
What is DI Container?
IoC Container (a.k.a. DI Container) is a framework for implementing automatic dependency injection. It manages object creation and it's life-time, and also injects dependencies to the class.
The IoC container creates an object of the specified class and also injects all the dependency objects through a constructor, a property or a method at run time and disposes it at the appropriate time. This is done so that we don't have to create and manage objects manually.
Font - tutorialsteacher
Registering dependencies
To register something on Container, you can use the InjectIdentifier directly or make an extension to create helpers to identify it.
Using key directly
Container.standard.register(key: "some_key") { _ in SomeObjc() }
Using type directly
Container.standard.register(type: FetchService.self) { _ in GitHubService() }
Using type with key variants
Container.standard.register(type: FetchService.self, key: "github") { _ in GitHubService() }
Container.standard.register(type: FetchService.self, key: "gitlab") { _ in GitlabService() }
Creating shortcuts to identify by extension
extension InjectIdentifier {
static var githubService: InjectIdentifier<FetchService> { .by(type: FetchService.self, key: "github") }
static var gitlabService: InjectIdentifier<FetchService> { .by(type: FetchService.self, key: "gitlab") }
static var externalService: InjectIdentifier<ExternalSingletonService> { .by(type: ExternalSingletonService.self) }
}
Registering with shortcuts
Container.standard.register(.githubService) { _ in GitHubService() }
Container.standard.register(.gitlabService) { _ in GitlabService() }
Container.standard.register(.externalService) { _ in ExternalSingletonService.shared }
Register using other dependencies
Container.standard.register(.gitlabService) { resolver in
let externalService = try resolver.resolve(.externalService)
return GitlabService(externalService)
}
Resolving dependencies
To resolve your dependencies, you have two ways. You can access the Container
directly or use @Injected
to do it automatically.
Using resolve from Container
let githubService = try? Container.standard.resolve(.githubService)
let gitlabService = try? Container.standard.resolve(.by(type: FetchService.self, key: "gitlab"))
let externalService = try? Container.standard.resolve(.by(type: ExternalSingletonService.self))
Using injection with @propertyWrapper
If you use @Injected
and have not injected yet, it will call fatalError
with an error message. If you do not want this behavior, you should use @InjectedSafe
, but using @InjectedSafe
, you will get an optional result.
@Injected(.githubService)
var githubService: FetchService
@InjectedSafe(.by(type: FetchService.self, key: "gitlab"))
var gitlabService: FetchService?
@Injected
var externalService: ExternalSingletonService
Instalation
Swift Package Manager
in Package.swift
add the following:
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/Tavernari/DIContainer", from: "0.2.0")
],
targets: [
.target(
name: "MyProject",
dependencies: [..., "DIContainer"]
)
...
]
Cocoapds
pod 'DIContainer-swift', '~> 0.2.0'