【问题标题】:Why does EnvironmentKey have a defaultValue property?为什么 EnvironmentKey 有一个 defaultValue 属性?
【发布时间】:2020-01-04 00:05:43
【问题描述】:

这是EnvironmentKey的定义:

public protocol EnvironmentKey {

    associatedtype Value

    static var defaultValue: Self.Value { get }
}

我对@9​​87654324@ 属性的用途感到困惑。或者我对@Environment 的预期用途感到困惑。让我解释一下……

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

protocol MyInjector: EnvironmentKey {
  static var defaultValue: Foo {
    print("get default value!")
    return Foo()
  }
}

您会发现 SwiftUI 经常调用此属性(因此,实际上我将我的 defaultValue 定义为 static let)。

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

extension EnvironmentValues {
  var myInjector: Foo {
    get { self[MyInjector.self] }  <-----------------
    set { self[MyInjector.self] = newValue }
  }
}

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

@Environment(\.myInjector) var foo: Foo

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

我认为@Environment的内部实现需要在确定实际值之前设置这个默认值作为避免变量声明可选的一种方式。

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

class Bar: ObservableObject {
  @Environmenet(\.myInjector var foo: Foo
}

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

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

protocol MyInjector: EnvironmentKey {
  static let defaultValue = Foo()
}

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

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

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    IMO 有两个原因在这种模式下使用 defaultValue(我认为这是意图):

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-20
      • 2015-01-22
      • 1970-01-01
      • 2012-07-11
      • 1970-01-01
      • 2010-12-04
      • 2014-12-05
      • 1970-01-01
      相关资源
      最近更新 更多