简体   繁体   中英

Dependency Injection in Swift

I completely fell in love with Dependency Injection. I enjoy the way it gives you the possibility to follow SOLID principles, the way it prevents Spaghetti Code. I used Dagger in one of my Android project and everything is more clean, modular and testable. Now I'm working on a Swift project. I would like to follow this kind of design pattern without using any third-party libraries (due to lacks of the current codebase and project commitments). So, I decided to create an homemade implementation.

import UIKit

class DependencyContainer {
    private var dependencies = [String: AnyObject]()

    struct Static {
        static var instance: DependencyContainer?
    }

    static var shared: DependencyContainer {
        if Static.instance == nil {
            Static.instance = DependencyContainer()
        }

        return Static.instance!
    }

    init() {
        AppDelegate.print("Dependency container instantiated")
    }

    func resolve(_ classIdentifier: String) -> AnyObject {
        if dependencies[classIdentifier] == nil {
            dependencies[classIdentifier] = getClassInstance(classIdentifier)
        }

        return dependencies[classIdentifier]!
    }

    private func getClassInstance(_ classIdentifier: String) -> AnyObject {
        var instance: AnyObject! = nil
        let classInstance = NSClassFromString(classIdentifier) as! NSObject.Type
        instance = classInstance.init()

        return instance
    }

    func dispose() {
        DependencyContainer.Static.instance = nil
    }
}

Where I need to inject a dependency I do it as follows:

dataRepository = DependencyContainer.shared.resolve(NSStringFromClass(DataRepositoryImplementation)) as! DataRepository

Everything is working fine at the moment but I think that there are lots of limitations with this kind of approach. Do you have any suggestions?

Yes, with your approach you'll need to register all your application objects to a single container. Also you're not using Generics to infer the type you're resolving and make your container Type-safe.

You can use https://github.com/JulianAlonso/Injection , it's type safe, have granularity, and its a very lightweight library.

I know an ultra-light dependency injection container. DIContainer

It's nice because you can resolve the dependencies using @Injected before the properties, or if you prefer, you can call the method resolve .

For example:

@Injected(.githubService)
var githubService: FetchService

@Injected(.by(type: FetchService.self, withKey: "gitlab"))
var gitlabService: FetchService

@InjectedSafe
var externalService: ExternalSingletonService?

or

let githubService = try? Container.standard.resolve(.githubService)
let gitlabService = try? Container.standard.resolve(.by(type: FetchService.self, withKey: "gitlab"))
let externalService = try? Container.standard.resolve(.by(type: ExternalSingletonService.self))

I hope it helps you with your achievement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM