DependencyContainer

public final class DependencyContainer : DependencyResolver
extension DependencyContainer: CustomStringConvertible

A DependencyContainer is used to create and access instances of services that the SDK needs in a configurable way, using inversion of control (IoC).

Container

Interactions with dependencies will happen through a container. You start by creating one (or multiple) containers to register services required for booting the framework or application.

    let container = DependencyContainer()

Factory

The most common method for registering dependencies is by associating a protocol or type to a factory. This will ensure a new instance of your dependency is created everytime it is resolved.

container.register { ServiceImplementation() as ServiceInterface }

It is also possible to explicitly define the type as argument.

container.register(as: ServiceInterface.self) { ServiceImplementation() }

Resolution

You can resolve a concrete instance of protocol or type using the container.

    let object = try! container.make() as ServiceInterface

It is also possible to specify the type in parameter instead.

    let object = try! container.make(ServiceInterface.self)

Warning

The order in which dependencies are registered is not relevant, as long as:
  • your dependencies resolve types that have been registered previously
  • you don’t register a dependency for a type already registered

Note that overriding dependency registrations may be desired to allow custom injections replacing default types for example, but you must then carefully check the order of registrations.

Scopes

Singleton Instance

You can also register an initialized instance of a dependency, which will be reused by the container while resolving the dependency.

container.register(ServiceImplementation(), as: ServiceInterface.self)

Or specify the singleton scope while registering a factory, which will resolve the factory only once and then reuse the same instance.

container.register(.singleton) { ServiceImplementation() as ServiceInterface }

Shared Instances

Sometimes you need to register different factories or different implementations of the same protocol. By default, if you register a dependency for the same type multiple times, the latest definition will override a previous one. This is called the unique scope.

To solve that, you can use shared dependencies by providing a shared scope with a specific context to the register method:

container.register(.shared(.myContext)) { ServiceImplementation() as ServiceInterface }
container.register(.shared(.anotherContext)) { ServiceImplementation() as ServiceInterface }

When you provide a context to resolve, container will look for a dependency associated with this context:

let object = try! container.make(ServiceInterface.self, context: .myContext)
let anotherObject = try! container.make(ServiceInterface.self, context: .anotherContext)

Dependency Provider

In order to organize dependencies in a better way, you can use multiple DependencyProvider to register all dependencies you would like to provide.

    let networkingProvider = NetworkingDependencyProvider()
    let securityProvider = SecurityDependencyProvider()
    container.register(providers: [ networkingProvider, securityProvider ])
  • The default scope used by the container.

    Declaration

    Swift

    public static let defaultScope: DependencyContainer.Scope
  • Creates a new container instance by passing a configuration closure.

    Declaration

    Swift

    public convenience init(configure: (DependencyContainer) -> ())

    Parameters

    configure

    A closure that allows to register dependencies directly at initialization.

  • Creates a new container instance by passing a list of providers to register.

    Declaration

    Swift

    public convenience init(providers: [DependencyProvider])

    Parameters

    providers

    A list of dependency providers to register.

Registering Dependencies

  • Registers a given instance conforming to a single interface. That same instance will always be returned on subsequent calls into the container.

    Declaration

    Swift

    public func register<T>(_ instance: T, as type: T.Type)

    Parameters

    instance

    An initialized instance to register.

    type

    A type (like a protocol) that the instance supports.

  • Registers a creating closure (factory). A new instance of the registered interface will be created and returned on subsequent calls into the container.

    Declaration

    Swift

    public func register<T>(_ scope: Scope = DependencyContainer.defaultScope, _ factory: @escaping () throws -> T)

    Parameters

    scope

    The strategy to use to manage resolved instances life cycle.

    factory

    A closure that returns an initialized instance to be registered.

  • Registers a creating closure (factory) conforming to an interface.

    Declaration

    Swift

    public func register<T>(as type: T.Type, _ scope: Scope = DependencyContainer.defaultScope, factory: @escaping () throws -> T)

    Parameters

    type

    A type (like a protocol) that the instance created by the factory supports.

    scope

    The strategy to use to manage resolved instances life cycle.

    factory

    A closure that returns an initialized instance to be registered.

  • Registers dependency providers that will automatically register all of the provider’s dependencies.

    A DependencyProvider allows to group dependency registrations.

    Declaration

    Swift

    public func register(providers: [DependencyProvider])

    Parameters

    providers

    A list of dependency providers to register.

Resolving Dependencies

  • Declaration

    Swift

    public func make<T>(_ type: T.Type = T.self) throws -> T
  • Declaration

    Swift

    public func make<T>(_ type: T.Type = T.self, context: Scope.Context? = nil) throws -> T

Dependency Container

  • Declaration

    Swift

    public var description: String { get }

Identifying Dependencies

Dependency Errors

  • The list of errors returned by the dependency container.

    See more

    Declaration

    Swift

    enum Error : Swift.Error, LocalizedError