SwiftUI:@Environment 未在视图层次结构中接收提供的值
Posted
技术标签:
【中文标题】SwiftUI:@Environment 未在视图层次结构中接收提供的值【英文标题】:SwiftUI: @Environment not receiving provided value down the view hierarchy 【发布时间】:2021-03-23 10:59:08 【问题描述】:我正在按照 this project 的示例创建我的 ios 应用程序(感谢 Alexey!),但无法让 @Environment 变量接收正在向下传递 UI 层次结构的值。***视图接收正确的值,但下游视图接收default
值。
编辑:在复制 Asperi 的代码之后,我发现只有在通过NavigationLink
调用下游视图时才会发生这种行为。更新以下代码:
EDIT2:问题在于调用environment
方法的位置。在NavigationView
而不是MainView
上调用它解决了这个问题。代码更新如下:
自定义环境键 - DIContainer
struct DIContainer: EnvironmentKey
let interactor: Interactor
init(interactor: Interactor)
self.interactor = interactor
static var defaultValue: Self Self.default
private static let `default` = Self(interactor: .stub)
extension EnvironmentValues
var injected: DIContainer
get self[DIContainer.self]
set self[DIContainer.self] = newValue
App
结构体
private let container: DIContainer
init()
container = DIContainer(interactor: RealInteractor())
var body: some Scene
WindowGroup
NavigationView
MainView()
.environment(\.injected, container)
主视图
struct MainView: View
@Environment(\.injected) private var injected: DIContainer
// `injected` has the `RealInteractor`, as expected
var body: some View
VStack
Text("Main: \(injected.foo())") \\ << Prints REAL
NavigationLink(destination: SearchView())
Text("Search")
搜索视图
struct SearchView: View
@Environment(\.injected) private var injected: DIContainer
// `injected` has the `StubInteractor`, why?
var body: some View
Text("Search: \(injected.foo())")
我可以通过像这样修改MainView
来解决这个问题:
var body: some View
SearchView()
.environment(\.injected, container)
但是@Environment
的目的不是避免重复这样做吗?
任何指导/指针表示赞赏。
【问题讨论】:
【参考方案1】:我尝试复制所有部分并编译它们...结果按预期工作 - 环境在视图层次结构中向下传递,因此您可能会在实际代码中遗漏某些内容。
这是完整的模块,使用 Xcode 12.4 / iOS 14.4 测试
class Interactor // << replicated !!
static let stub = Interactor()
func foo() -> String "stub"
class RealInteractor: Interactor // << replicated !!
override func foo() -> String "real"
struct ContentView: View // << replicated !!
private let container: DIContainer
init()
container = DIContainer(interactor: RealInteractor())
var body: some View
NavigationView
MainView()
.environment(\.injected, container) // << to affect any links !!
// no changes in env parts
struct DIContainer: EnvironmentKey
let interactor: Interactor
init(interactor: Interactor)
self.interactor = interactor
static var defaultValue: Self Self.default
private static let `default` = Self(interactor: .stub)
extension EnvironmentValues
var injected: DIContainer
get self[DIContainer.self]
set self[DIContainer.self] = newValue
struct MainView: View
@Environment(\.injected) private var injected: DIContainer
// `injected` has the `RealInteractor`, as expected
var body: some View
SearchView()
// just tested here
struct SearchView: View
@Environment(\.injected) private var injected: DIContainer
var body: some View
Text("Result: \(injected.interactor.foo())") // << works fine !!
【讨论】:
哇!没想到任何人都会如此尽职尽责。谢谢!在我尝试复制回您的工作环境后,我发现我的SearchView
在 NavigationLink
中被调用,这导致了问题。
在NavigationView
上调用environment
方法解决了我的问题。您能否为未来的编码人员更新您的答案,我可以接受吗?以上是关于SwiftUI:@Environment 未在视图层次结构中接收提供的值的主要内容,如果未能解决你的问题,请参考以下文章
我如何在swiftui中从我的应用程序中的任何视图访问这个:@Environment(\.managedObjectContext) var context? [关闭]
添加 ViewModel 后,SwiftUI 视图未在按钮切换上更新