Dependency Injection

In the source code from the Example App you can see how the Data Manager inside the App Dependencies struct is used through the whole hierarchy.

You define a global struct that conforms to the AppDependenciesProtocol protocol and will hold all the necessary dependencies on your app

struct AppDependencies: AppDependenciesProtocol {

    let dataManager: DataManager

    init() {
        self.dataManager = DataManager()
    }

    func start(with completion: @escaping () -> Void = {}) {
        self.dataManager.start {
            completion()
        }
    }
}

On the first Coordinator in the hierarchy you need to initiate it, like in Example App AppCoordinator

...
override func start(with completion: @escaping () -> Void = {}) {

    // Do not use the direct self.dependencies = dependencies way, because this method does additional things
    self.setDependencies(dependencies:  AppDependencies())

    self.dependencies?.start { [weak self] in
        ...
    }

    super.start(with: completion)
}
...

and then from there on, you only need to conform to the HasDependencies protocol on the Coordinators that you want to have access to the dependencies. Coordinate takes care of injecting them automatically on the children Coordinators for your convenience.

class MainCoordinator: TabBarCoordinator<MainViewController>, HasDependencies {

    var dependencies: AppDependencies?
    ...

Use the struct you created as a dependencies holder to conform to HasDependencies protocol, as shown in the example above. Do not use AppDependenciesProtocol.

The inspiration for this system comes from here, where you can also read why it is a better solution for this problem.

Found errors? Think you can improve this documentation? Simply click the Edit link at the top of the page, and then the icon on Github to make your changes.