A lightweight, simple, and type-safe dependency injection library for Swift.
Add the following to your Package.swift file:
dependencies: [
.package(url: "https://github.com/nts-sixblack/SwiftInjected.git", from: "2.0.0")
]First, create a protocol and a concrete implementation for your service.
protocol NetworkServiceProtocol {
func fetch()
}
class NetworkService: NetworkServiceProtocol {
func fetch() {
print("Fetching data...")
}
}You need to register your dependencies at the start of your application (e.g., in AppDelegate or SceneDelegate).
import SwiftInjected
// Configure dependencies
let dependencies = Dependencies {
Dependency { NetworkService() }
}
// Build the dependency graph
dependencies.build()Use the @Injected property wrapper to inject the dependency into your classes or structs.
import SwiftInjected
class MyViewModel {
@Injected var networkService: NetworkService
func loadData() {
networkService.fetch()
}
}For SwiftUI views observing an ObservableObject, use @InjectedObservable.
import SwiftUI
import SwiftInjected
class MyViewModel: ObservableObject, NetworkServiceProtocol {
@Published var data: String = ""
// ...
}
struct MyView: View {
@InjectedObservable var viewModel: MyViewModel
var body: some View {
Text(viewModel.data)
}
}Starting in version 2.0.0, calling dependencies.build() registers dependencies to be resolved lazily on first access. This improves startup performance and prevents unnecessary initialization:
dependencies.build() // Resolves dependencies on first accessIf you prefer eager resolution (for example, to validate the entire dependency graph at startup), use buildEager():
dependencies.buildEager() // Resolves all dependencies immediatelyResolution is thread-safe using an internal lock, and lookups are optimized to O(1) via type identifiers.
By default, the dependency name is the class name. You can customize it if needed, although the current implementation primarily uses type inference.
You can also resolve dependencies manually if needed, though @Injected is preferred.
let service: NetworkService = Dependencies.shared.resolve() // Internal method, prefer @Injected(Note: Dependencies.shared is used internally by the property wrapper).
This library is released under the MIT License.