SwiftDependencyContainer is a lightweight Dependency Container leveraging code generation to make setting up and managing dependencies easier than ever.
Objects registered as Singleton are retained throughout the container's' lifetime, once resolved. Marked as eager will create the instance immediately, when the bootstrap method is called. Objects registered as Factory will return a new instance every time it's being resolved.
Required dependencies to instantiate an object using constructor injection can be auto-wired, assuming they are registered in the container.
Register one instance for multiple types, allowing for more flexible and maintainable code.
Manage dependencies using hashable keys, enabling registering different implementations for the same protocol or tpye.
For a magical setup experience thanks to code generation.
Examples contains a demonstration for each use case.
You can use the following annotiations for automatic dependency resolution:
/// @Singleton
/// @EagerSingleton
/// @Singleton(types: [])
/// @EagerSingleton(types: [])
/// @FactoryThis is the entry point of your depdencies.
All it takes is an object that confirms to the AutoSetup protocol.
import SwiftDependencyContainer
struct MyDependencies: AutoSetup {
let container = DependencyContainer()
}After building your project, all necessary code for registering and resolving dependencies will be automatically generated and available.
To bootstrap your DependencyContainer call the setup method of your type implementing AutoSetup.
MyDependencies.setup()Note: You won't be able to register any more dependencies after setup has been called.
At this point you are ready to go. No more code that needs to be written!
There are two ways to access your dependencies:
/// @Singleton
class MyType {}Direct Access
All your dependencies have a resolve method, which can be used to get the instance from the DependencyContainer.
MyType.resolve() // generatedComposition Root Access
Every registered dependency is also available as static var at your type implementing AutoSetup.
MyDependencies.myType // generatedAutoSetup is great and convinient, but some scenarios require more flexibility.
Manually register dependencies if needed by overrideing the optional override method of the AutoSetup protocol.
struct MyDependencies: AutoSetup {
let container = DependencyContainer()
func override(_ container: DependencyContainer) throws {
try container.register(Storage.self) { UserDefaults() } // register
}
static var storage: Storage { resolve() } // resolve
}Note: Please feel free to open a ticket if you feel like the usage of your override should be part of this framework!
Take a look at Examples for more details.
For those who prefer the traditional way:
let container = DependencyContainer()try container.register { Singleton1() }
// resolve other co-dependencies
try container.register { Singleton2(other: try $0.resolve()) }
// register instance for another type
try container.register(Abstraction.self) { Singleton1() }
// register instance for several other types
try container.register([Abstraction1.self, Abstraction2.self]) { Singleton1() }
// register instance for a key
try container.register("MyKey") { Singleton1() }All register methods include an isEager: Bool parameter. Eager dependencies are resolved upon container bootstrap.
Note: Keys are required to be Hashable.
try container.bootstrap()let singleton: Singleton1 = try container.resolve()
let singleton1: Singleton1 = try container.resolve("MyKey")
let singleton2: Abstraction2 = try container.resolve()You can use the Swift Package Manager to install SwiftDependencyContainer by adding it as a dependency to your Package.swift file:
dependencies: [
.package(url: "git@github.com:davidscheutz/SwiftDependencyContainer.git", from: "0.2.0")
]Make sure to add SwiftDependencyContainer as a dependency to your Target.
Select your Project -> Your Target -> Build Phases -> Add CodeGeneratorPlugin (SwiftDependencyContainer)
The codegen runs now as part of the build phase, every time you compile your project.
Contributions to SwiftDependencyContainer are welcomed and encouraged!
It is easy to get involved. Open an issue to discuss a new feature, write clean code, show some love using unit tests and open a Pull Request.
A list of contributors will be available through GitHub.
PS: Check the open issues and pull requests for existing discussions.
SwiftDependencyContainer is available under the MIT license.
This project uses Sourcery for the code generation.