DependencyContainer is an implementation of dependency injection for Swift applications, designed to simplify service management and improve code modularity.
This dependency injection container allows you to define, register, and resolve services in a clean and type-safe manner, facilitating better management of dependencies in your SwiftUI applications.
To begin using the container, you first need to define keys for your services. These keys are used to identify the services when registering and resolving them.
extension DI {
static let network = Key<any Network>()
static let dataManager = Key<any DataManager>()
static let settings = Key<any Settings>()
}
Next, you will register your services within the DI.Container. This step associates each service with its corresponding key.
extension DI.Container {
static func setup() {
register(DI.network, NetworkImp())
register(DI.dataManager, DataManagerImp())
register(DI.settings, SettingsImp())
}
}
You can access the registered services in your classes by using the provided property wrappers. For example, in a class that conforms to ObservableObject, you can inject dependencies as follows:
class SomeStateObject: ObservableObject {
@DI.Static(DI.network, \.tokenUpdater) var network
@DI.RePublished(DI.settings) var settings
}
The RePublished
property wrapper automatically redirects updates from the injected service to the enclosing ObservableObject
, ensuring your UI stays in sync with the underlying data.
RePublished property wrapper redirects update from a service to a container ObservableObject
In SwiftUI views, you can also inject and observe your services. For example:
struct SomeView: View {
@DI.Observed(DI.dataManager) var data
var body: some View {
// Your view content using the injected data manager
}
}
Ilya Kuznetsov – i.v.kuznecov@gmail.com
Distributed under the MIT license. See LICENSE
for more information.