Discoverer is a lightweight, multiplatform dependency injection utility written in pure Swift.
Requirements
Development
Project uses following tools for development
Installation
To get started with the Discoverer you first have to decide how you will integrate it with your project. Discoverer supports following tools:
Cocoapods
To install Discoverer using Cocoapods go through following steps:
- Add the following entry in your Podfile:
pod 'Discoverer'
- Then run
pod install
.
Carthage
To install Discoverer using Carthage go through following steps:
- Add the following entry to your Cartfile
github "lewandowskit93/Discoverer"
- Then run
carthage update
Swift Package Manager
To install Discoverer using Swift Package Manager go through following steps:
- Add following package dependency in you Package.swift
.package(url: "https://github.com/lewandowskit93/Discoverer.git", from: "0.0.3")
- Add following target dependency in your Package.swift
dependencies: ["Discoverer"])
For instance this is how it might look like:
import PackageDescription
let package = Package(
name: "YourLibrary",
products: [
.library(
name: "YourLibrary",
targets: ["YourLibrary"])
],
dependencies: [
.package(url: "https://github.com/lewandowskit93/Discoverer.git", from: "0.0.3")
],
targets: [
.target(
name: "YourLibrary",
dependencies: ["Discoverer"])
]
)
Overview
Here is a quick overview of functionalities and concepts used in Discoverer.
Injection
Injection is an enum which represents single Injection. It can be one of:
- Singleton - returns same instance everytime e.g.:
Injectable<PFoo>.singleton(Foo())
- LazySingleton - if there is no instance it uses factory to create one, then it returns this instance everytime e.g.:
Injectable<PFoo>.lazySingleton(nil, { Foo() })
- Factory - returns new instance everytime e.g.:
Injectable<PFoo>.factory({ Foo() })
Injector
Injector manages injected services. It grants access to the service by providing:
- subscript - returning service as optional (nil if not registered) e.g.:
injector[PFoo.self]
- getter - returning service and throwing error if not registered e.g.:
injector.get(PFoo.self)
Injected
Injected is a property wrapper that marks a property as injected with the service provided by given Injector. Example usage:
@Injected var foo: PFoo
Injected also allows you to specify which container to use as follows:
@Injected(injector: Environment.services) var serviceA: PServiceA
Registered
Registered is a property wrapper that marks an injection as registered in given Injector. Example usage:
@Registered
var serviceAInjection = Injection<PServiceA>.singleton(ServiceA())
Registered also allows you to specify which container to use as follows:
@Registered(inInjector: Environment.services)
var serviceAInjection = Injection<PServiceA>.singleton(ServiceA())
Example
Given the environment
struct Environment {
static var services: Injector = Injector()
static var repositories: Injector = Injector()
}
We could define following services and repositories:
protocol PServiceA {
func foo()
}
class ServiceA: PServiceA {
func foo() {
print("Service A")
}
}
protocol PRepositoryB {
func foo() -> String
}
class RepositoryB: PRepositoryB {
func foo() -> String {
return "foo"
}
}
Then configure the injector as follows:
struct Configurator {
static func configure(repositories: Injector, services: Injector) throws {
_ = try? repositories
.register(as: PRepositoryB.self, injectable: .singleton(RepositoryB()))
_ = try? services
.register(as: PServiceA.self, injectable: .factory({ ServiceA() }))
}
}
or:
struct Configurator {
@Registered(inInjector: Environment.repositories)
var repositoryBInjection = Injection<PRepositoryB>.factory({ RepositoryB() })
@Registered(inInjector: Environment.services)
var serviceAInjection = Injection<PServiceA>.singleton(ServiceA())
}
The second approach requires creating an instance of Configurator, so that injections are registered.
Then inject dependencies into ViewModel:
struct FooViewModel {
@Injected(injector: Environment.services) var serviceA: PServiceA
@Injected(injector: Environment.repositories) var repositoryB: PRepositoryB
}
For more detailed example please see the source code.
Contribution
Project is created and maintained by Tomasz Lewandowski.
If you created some new feature or fixed a bug you can create a pull request. Please feel free to submit your feature requests if you have any.
License
Discoverer is released under an MIT license. See License.md for more information.