为什么 EnvironmentKey 有一个 defaultValue 属性?

Gil*_*man 5 swift swiftui

这是 的定义EnvironmentKey

public protocol EnvironmentKey {

    associatedtype Value

    static var defaultValue: Self.Value { get }
}
Run Code Online (Sandbox Code Playgroud)

我对defaultValue财产的目的感到困惑。或者我对@Environment. 让我解释...

根据我的测试,我知道defaultValue正在访问 。例如,如果您将 定义defaultValue为 getter:

protocol MyInjector: EnvironmentKey {
  static var defaultValue: Foo {
    print("get default value!")
    return Foo()
  }
}
Run Code Online (Sandbox Code Playgroud)

你会发现 SwiftUI 经常调用这个属性(因此,在实践中我将 my 定义defaultValuestatic let)。

当您在打印语句上添加断点并向下移动堆栈时,它会停在下面的箭头处:

extension EnvironmentValues {
  var myInjector: Foo {
    get { self[MyInjector.self] }  <-----------------
    set { self[MyInjector.self] = newValue }
  }
}
Run Code Online (Sandbox Code Playgroud)

在堆栈的更下方是init我访问以下变量的组件中的行:

@Environment(\.myInjector) var foo: Foo
Run Code Online (Sandbox Code Playgroud)

也就是说,它似乎可以随时访问defaultValue带有@Environment变量的 SwiftUI 视图被重新渲染。

我认为内部实现@Environment需要在确定实际值之前设置这个默认值,以避免将变量声明设为可选。

最后,我还尝试添加@Environment到 anObservableObject中,希望它能够访问与 SwiftUI 视图树相同的“环境”。

class Bar: ObservableObject {
  @Environmenet(\.myInjector var foo: Foo
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,情况并非如此,Bar收到的实例与我通过View.environment(\.myInjector, Foo()).

我还发现,顺便说一句,我可以使用@Environment共享变量模式来注入全局单例:

protocol MyInjector: EnvironmentKey {
  static let defaultValue = Foo()
}
Run Code Online (Sandbox Code Playgroud)

并且相同的实例可用于 SwiftUI 视图和任何其他类,但我不确定这有什么用处。

那么目的是defaultValue什么?正如我所怀疑的那样,它是简单的,以便内部实现可以在确定真实值之前为变量分配一个任意值,还是有其他事情发生?

Asp*_*eri 2

在我看来,采用这种模式有两个原因defaultValue(我认为这就是意图):

1) 指定相应的值类型
2) 使环境值始终有效(使用时@Environment

SwiftUI: Set Status Bar Color For a Specific View帖子中,您可以找到使用此功能的示例defaultValue,以便通过环境轻松连接应用程序的不同部分。