DICE
DICE 是一个轻量级的 Swift 框架,为 Swift 和 SwiftUI 项目的属性库提供基于属性的依赖注入。DICE 还提供通过容器的服务定位模式。通过属性包装器或通过 DI 容器轻松注入依赖项。DICE 支持不同的作用域(单例、懒加载弱引用、懒加载原型、懒加载对象图)。
系统要求
- Swift 5.1
- iOS 13.0
安装
DICE 可通过 CocoaPods 获取。要安装它,只需将以下行添加到 Podfile 中
pod 'DICE'
示例
要运行示例项目,首先克隆仓库,然后从 Example 目录运行 pod install
。
使用方法
通过DI容器注入
1. 添加导入
import DICE
2. 声明你的容器
let container = DIContainer()
3. 注册你的实例
container.register(DummyServiceType.self) { _ in
return DummyService()
}
例如,DummyServiceType只是一个协议,而DummyService是一个实现。
protocol DummyServiceType {
func test()
}
class DummyService: DummyServiceType {
func test() {
Swift.print("DummyService")
}
}
4. 将容器传递给DICE
DICE.use(container)
5. 解析实例
使用DIContainer
import UIKit
import DICE
class ViewController: UIViewController {
let container = DIContainer()
// In real case you'll need to pass container in ViewController or another class and all the dependencies should have been already registered prior to using container
override func viewDidLoad() {
super.viewDidLoad()
container.register(DummyServiceType.self, scope: .single) { _ in
return DummyService()
}
DICE.use(container)
let service: DummyServiceType = container.resolve()
service.test()
// It should print "DummyService" in Xcode console
// If you get error here, so check previous steps or open an issue
}
}
使用@Injected属性包装器
import UIKit
import DICE
class ViewController: UIViewController {
@Injected var dummyService: DummyServiceType
override func viewDidLoad() {
super.viewDidLoad()
dummyService.test()
// It should print "DummyService" in Xcode console
// If you get error here, so check previous steps or open an issue
}
}
在SwiftUI中注入
EnvironmentObservableInjected
自动订阅并使视图在变化时自动无效化的动态视图属性包装器。
struct ContentView: View {
@EnvironmentObservableInjected var viewModel: ContentViewModel
var body: some View {
HStack {
Text(viewModel.title)
}.onAppear { self.viewModel.startUpdatingTitle() }
}
}
...
class ContentViewModel: ObservableObject {
@Published private(set) var title: String = ""
func startUpdatingTitle() {
self.title = "Test"
}
}
EnvironmentInjected
从环境容器注入对象的属性包装器。只读对象。通常用于不可变对象。
struct ContentView: View {
@EnvironmentInjected var service: WebService
var body: some View {
HStack {
Text("Waiting...")
}.onAppear { self.service.auth() }
}
}
高级用法
作用域
默认范围
默认范围为 DIScope.objectGraph
。在注册对象时如果没有设置范围,所有已注册的对象都将使用默认范围。可以通过设置 DICE.Defaults.scope
来修改,例如
DICE.Defaults.scope = .single
支持的范围
DIScope.single
依赖项在每个容器中按单例创建。建议用于一旦注入到 DIContainer
就应实例化的单例。
DIScope.weak
依赖项会在每个容器中懒加载创建,但在依赖对象即将 deinited 时销毁。只有在第一次调用后对象才会实例化。
DIScope.prototype
依赖项实例每次都会懒加创建。对象仅在实际调用后第一个调用才会实例化。
DIScope.objectGraph
依赖项实例在每个对象图中固定懒加创建,对象也仅在实际调用后第一个调用才会实例化。
设置范围
您可以在注册对象时使用可选的 scope
参数来指定范围。如果没有传递范围,则使用默认范围 DIScope.Defaults.scope
。
container.register(InjectableServiceType.self, scope: .objectGraph) { _ in
return InjectableService()
}
在注入时使用容器解析器
假设 InjectableService
需要在初始化器中接收 InternalServiceType
作为依赖项。
class InjectableService: InjectableServiceType {
let internalService: InternalServiceType
init(internalService: InternalServiceType) {
self.internalService = internalService
}
}
- 注册
InternalServiceType
container.register(InternalServiceType.self) { _ in
return InternalService()
}
- 在注册
InjectableServiceType
并将其传递给InjectableService
时,从容器中解析InternalServiceType
container.register(InjectableServiceType.self) { container in
let internalService: InternalServiceType = container.resolve()
return InjectableService(internalService: internalService)
}
标记
在注册依赖时,您可以为一个对象分配一个标签。当您使用 DIContainer.resolve()
或属性包装器 Injected
、EnvironmentObservableInjected
、EnvironmentInjected
来解析依赖时,可以使用标签来注入匹配您传入标签的对象。
使用标签注册依赖
container.register(InternalServiceType.self, tag: "dependency1") { _ in
return InternalService(test: "stringInternal")
}
使用标签解析依赖
假设我们想要注入类型为 InternalServiceType
且标签为 dependency1
的 InternalService
。
- 使用
DIContainer.resolve()
进行解析
let service: InternalServiceType = container.resolve(tag: "dependency1")
- 使用属性包装器进行解析
@Injected("dependency1") var service: InternalServiceType
版本控制
版本号遵循 语义化版本控制 方式。
沟通与帮助
- 如果您需要帮助,请使用 Stack Overflow(标签'dice')或 提交问题。
- 如果您想提出一般性问题,请使用 Stack Overflow 或 提交问题。
- 如果您发现了bug,请 提交问题。
- 如果您有功能请求,请 提交问题。
- 如果您想进行贡献,提交 pull request。
- 如果您使用并喜欢DICE,请在GitHub上为项目点赞。
参与贡献
我们非常乐意接受来自社区的贡献,这就是我们把它开源的主要原因!
- 进行Fork([https://github.com/DICE-Swift/dice/fork)(https://github.com/DICE-Swift/dice/fork)
- 创建你的功能分支(git checkout -b feature/fooBar)
- 提交你的更改(git commit -am '添加一些fooBar')
- 推送到分支(git push origin feature/fooBar)
- 创建一个新的[https://github.com/DICE-Swift/dice/pulls](https://github.com/DICE-Swift/dice/pulls)pull请求
贡献者
维护者
贡献者
想成为第一个贡献者吗?请建议您通过贡献部分来改进。
许可证
DICE遵循MIT许可证。有关更多信息,请参阅LICENSE文件。