DIKit 1.6.0

DIKit 1.6.0

Ben John 维护。



DIKit 1.6.0

DIKit

Swift 的依赖注入框架,受 KOIN 启发。它基本是一个服务定位模式的实现,生活于应用程序上下文中。

随着需要而发展!

我们从一个小项目开始,它完美适合我们的用例。

安装

通过 Carthage

您可以使用 Carthage 进行 DIKit 的安装。安装 Carthage 后,只需将 DIKit 添加到您的 Cartfile 中。

github "Liftric/DIKit" ~> 1.6

通过 CocoaPods

CocoaPods 是一个用于 Swift 和 Objective-C Cocoa 项目的依赖管理器。安装 CocoaPods 后,将 DIKit 添加到您的 Podfile 中。

platform :ios, '9.0'
pod 'DIKit', '~> 1.6'

基本用法

  1. 定义一些子 DependencyContainer(基本上是一种模块声明)
import DIKit

public extension DependencyContainer {
    static var backend = module {
        single { Backend() as BackendProtocol }
    }
}

public extension DependencyContainer {
    static var network = module {
        single { Network() as NetworkProtocol }
    }
}

public extension DependenyContainer {
    static var app = module {
        single { AppState() as AppStateProtocol }
        factory { StopWatch() as StopWatchProtocol }
    }
}
  1. 设置根 DependencyContainer 并在应用程序初始化之前设置
import DIKit

@UIApplicationMain
class AppDelegate: UIApplicationDelegate {
    override init() {
        super.init()
        DependencyContainer.defined(by: modules { .backend; .network; .app })
    }
}

如果没有子 DependencyContainer,以下简写方式也可以完成工作

import DIKit

@UIApplicationMain
class AppDelegate: UIApplicationDelegate {
    override init() {
        super.init()
        DependencyContainer.defined(by: module {
            single { AppState() as AppStateProtocol }
            factory { StopWatch() as StopWatchProtocol }
        })
    }
}
  1. 注入依赖项,例如在模块中
import DIKit

class Backend: BackendProtocol {
    @Inject var network: NetworkProtocol
}

或一个 ViewController

import DIKit

class FirstViewController: UIViewController {
    // MARK: - Dependencies
    @LazyInject var backend: BackendProtocol
    @OptionalInject var stopwatch: StopWatchProtocol?

    // MARK: - View lifecycle
    override func viewWillAppear(_ animated: Bool) {
        let result = backend.fetch()
        print(result)
    }
}

构造函数注入

import DIKit

struct AppState: AppStateProtocol {
    private let backend: BackendProtocol
    init(backend: BackendProtocol = resolve()) {
        self.backend = backend
    }
}

高级用法

按标签解析

在注册依赖项时,您可以可选地定义一个标签。标签可以是任何东西,只要它是 AnyHashable

这样,您可以注册相同类型的不同可解析依赖项。

enum StorageContext: String {
    case userdata
    case systemdata
}

public extension DependencyContainer {
    static var app = module {
        factory(tag: StorageContext.systemdata) { LocalStorage() as LocalStorageProtocol }
        factory(tag: StorageContext.userdata) { LocalStorage() as LocalStorageProtocol }
    }
}

然后您可以在解析类型时引用相同的标签,从而解析不同的实例。引用标签与所有注入方法一起使用。

import DIKit

class Backend: BackendProtocol {
    @Inject(tag: StorageContext.systemdata) var injectedStorage: LocalStorageProtocol
    @LazyInject(tag: StorageContext.systemdata) var lazyInjectedStorage: LocalStorageProtocol
    @OptionalInject(tag: StorageContext.systemdata) var optionalInjectedStorage: LocalStorageProtocol?
    
    private let constructorInjectedStorage: LocalStorageProtocol
    init(storage: LocalStorageProtocol = resolve(tag: StorageContext.systemdata)) {
        self.constructorInjectedStorage = storage
    }
}