Swiftpack.co - Package - egeniq/InjectPropertyWrapper


Provides a generic Swift @Inject property wrapper that can be used to inject objects / services from a dependency injection framework of your choice.

Basic Usage

First, you need to implement the Resolver protocol for the Dependency Injection (DI) framework you are using.

For example, when using Swinject:

extension Container: InjectPropertyWrapper.Resolver {

In case of Swinject the Container class already contains a method with the same signature (resolve<T>(_ type: T, name: String?)) as the InjectPropertyWrapper Resolver protocol requires.

Then you need to set the global resolver (for example in your app delegate):

let container = Container()
InjectSettings.resolver = container

Register some objects in the container:

container.register(APIClient.self) { _ in APIClient() }
container.register(MovieRepository.self) { _ in IMDBMovieRepository() }
container.register(MovieRepository.self, name: "netherlands") { _ in IMDBMovieRepository("nl") }

Now you can use the @Inject property wrapper to inject objects/services in your own classes:

class IMDBMovieRepository: MovieRepository {
    @Inject private var apiClient: APIClient
    func fetchTop10(completionHandler: @escaping (movies: [Movie]) -> Void) {

class MovieViewModel: BindableObject {
    public var didChange = PassthroughSubject<Void, Never>()
    public private(set) var top10: [Movie]? {
        didSet {

    @Inject private var movieRepository: MovieRepository
    func load() {
        movieRepository.fetchTop10() { [weak self] movies in
            self?.top10 = movies

It is also possible to inject different objects of the same type using the name parameter:

class MovieViewModel: BindableObject {
    @Inject private var globalMovieRepository: MovieRepository
    @Inject(name: "netherlands") private var nlMovieRepository: MovieRepository

Normally if the property wrapper is unable to resolve a dependency it will raise a non-recoverable fatal error. If for some reason you expect an object sometimes to be unavailable in your container, you can mark the property as optional:

class MovieViewModel: BindableObject {
    @Inject(name: "germany") private var deMovieRepository: MovieRepository?


To run the tests for this package make sure the ENABLE_TESTS environment variable is set to 1 or true. For example when using the command line:

ENABLE_TESTS=1 swift test

This allows the package to only load certain dependencies when testing.


This project is licensed under the terms of the MIT license. See the LICENSE file.


Stars: 21


Used By

Total: 0


0.3.0 -

Compatibility with Xcode 11 beta 3 and allow optional injections

0.2.0 -

Some small naming changes and better documentation + tests.