kvEnvironment

依赖注入模式的一种实现。kvEnvironment 提供

支持的平台

对于任何平台都没有明确的限制。因此,假设 kvEnvironment 可以在任何 Swift 可用的平台上编译。

入门指南

包依赖

.package(url: "https://github.com/keyvariable/kvEnvironment.git", from: "0.5.1")

目标依赖

.product(name: "kvEnvironment", package: "kvEnvironment")

导入

import kvEnvironment

作用域属性的声明

extension KvEnvironmentScope {
    #kvEnvironment { var someProperty: SomeType }
}

依赖注入

@KvEnvironment(\.someProperty) private var someProperty

示例

简单示例

以下示例展示了 C 依赖于 AB 的情况

struct A { let a: Int }

struct B { let b: String }

extension KvEnvironmentScope {
    #kvEnvironment {
        var a: A?
        var b: B = .init(b: "default")
    }
}

struct C {
    @KvEnvironment(\.a) private var a
    @KvEnvironment(\.b) private var b
}

环境属性 a 被声明为可选类型。#kvEnvironment 宏为可选类型提供了隐式默认值 nil。环境属性 b 被声明为不透明类型并且有一个默认值。因此,由于提供了默认值,C 可以在任何作用域的任何时刻被实例化。

如果一个环境属性在定义时没有默认值,那么它必须在其 getter 被调用之前显式地初始化。

作用域

有全局(KvEnvironmentScope.global)和任务本地(KvEnvironmentScope.current)作用域。可以创建独立或覆盖的作用域

// By default new scopes override global scope.
let aScope = KvEnvironmentScope {
    $0.a = A(a: 1)
}
// Parent scope can be explicitly provided.
// So in `abScope` both `a` and `b` properties are overridden.
let abScope = KvEnvironmentScope(parent: aScope) {
    $0.b = B(b: "custom")
}

以下是临时覆盖全局作用域的一种方式的示例

let c = C()

// Here dependencies are resolved in the global scope.
print(c)

// In block below current scope is changed to `abScope`.
abScope {
    // Here dependencies are resolved in `abScope`.
    print(c)
}

有几种方法可以为依赖引用提供显式的作用域

循环引用

struct E {
    let id: String

    @KvEnvironment(\.f) var f
}

struct F {
    let id: String

    @KvEnvironment(\.e) var e
}

extension KvEnvironmentScope {
    #kvEnvironment {
        var e: E
        var f: F
    }
}

struct G: CustomStringConvertible {
    @KvEnvironment(\.e) private var e
    @KvEnvironment(\.f) private var f
}

// Populating global scope with required values.
KvEnvironmentScope.global {
    $0.e = E(id: "e1")
    $0.f = F(id: "f1")
}

let g = G()
// e: "e1", f: "f1", e.f: "f1", f.e: "e1".
print(g)

作者