Swiftpack.co - Package - lewandowskit93/Discoverer

Build Status codecov Carthage compatible Cocoapods Platform Platform License

Discoverer is a lightweight, multiplatform dependency injection utility written in pure Swift.



Project uses following tools for development

  1. XCodeGen
  2. Cocoapods
  3. SwiftLint


To get started with the Discoverer you first have to decide how you will integrate it with your project. Discoverer supports following tools:


To install Discoverer using Cocoapods go through following steps:

  1. Add the following entry in your Podfile:
pod 'Discoverer'
  1. Then run pod install.


To install Discoverer using Carthage go through following steps:

  1. Add the following entry to your Cartfile
github "lewandowskit93/Discoverer"
  1. Then run carthage update

Swift Package Manager

To install Discoverer using Swift Package Manager go through following steps:

  1. Add following package dependency in you Package.swift .package(url: "https://github.com/lewandowskit93/Discoverer.git", from: "0.0.3")
  2. 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: [
            name: "YourLibrary",
            targets: ["YourLibrary"])
    dependencies: [
        .package(url: "https://github.com/lewandowskit93/Discoverer.git", from: "0.0.3")
    targets: [
            name: "YourLibrary",
            dependencies: ["Discoverer"])


Here is a quick overview of functionalities and concepts used in Discoverer.


Injection is an enum which represents single Injection. It can be one of:

  • Singleton - returns same instance everytime e.g.:
  • 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 manages injected services. It grants access to the service by providing:

  • subscript - returning service as optional (nil if not registered) e.g.:
  • getter - returning service and throwing error if not registered e.g.:


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 is a property wrapper that marks an injection as registered in given Injector. Example usage:

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())


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() }))


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.


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.


Discoverer is released under an MIT license. See License.md for more information.


Stars: 1


Used By

Total: 0


Discoverer 0.0.3 - 2020-02-07 18:03:59

  • Use default injector for injected & registered if none specified

Discoverer 0.0.2 - 2020-02-02 23:04:31

  • Renamed library Injector -> Discoverer

Discoverer 0.0.1 - 2020-02-02 19:04:11

Following features are available:

  • Add Injected property wrapper
  • Add Registered property wrapper
  • Add following injection modes: singleton, lazySingleton, factory
  • Add ability to register and discover services