不了解环境物体的动态和视图娱乐

问题描述 投票:0回答:1

我创建了在更复杂的应用程序中遇到的问题的简化版本。因此,您可以帮助我理解为什么事情没有按我的预期工作,而不是建议我重写代码吗?代码以这种奇怪的方式构建是有原因的,以类似于更复杂的情况。这是简化的测试代码 - 顶层视图是 TestEnvUpdate:

class GlobData: ObservableObject {
  var buttonText: String? = "hello"
  static let shared = GlobData()
  
  func setText(str: String?) {
    buttonText = str
    objectWillChange.send()
  }
}

struct TestEnvUpdate: View {
  var body: some View {
    ParentView().environmentObject(GlobData.shared)
  }
}

struct ParentView: View {
  @EnvironmentObject var globData: GlobData
  
  var body: some View {
    if globData.buttonText != nil {
      ChildView()
    } else {
      Text("buttonText is nil")
    }
  }
}

struct ChildView: View {
  @EnvironmentObject var globData: GlobData

  var body: some View {
    VStack {
      Text(globData.buttonText!)  // error occurs here
      Button ("set to nil") { globData.setText(str: nil) }
    }
  }
}

当我按下“设置为 nil”按钮时,GlobData setText 函数将运行,并且 objectWillChange.send() 函数将运行。然后,我期望 ParentView 主体函数运行,请注意,buttonText 设置为零,并且不尝试创建 ChildView,因为 ParentView 依赖于环境对象。但相反,ChildView 运行并崩溃,因为 ButtonText 为零。

任何人都可以解释为什么会发生这种情况,以及 objectWillChange.send() 的排序如何工作吗?使用 objectWillChange.send() 时是否存在任何线程问题或任何延迟操作?

我有一种感觉,这个问题的答案将加深我对 SwiftUI 在视图层次结构中排序视图创建方式的理解。

swiftui environmentobject
1个回答
0
投票

globData
ChildView
的依赖项。当 SwiftUI 观察到
globData
发生变化时(因为您调用了
objectWillChange.send()
),它需要调用
ChildView.body
来查看发生了什么变化。

是的,无论如何,

ChildView
都会消失,因为
if
中的
ParentView
,但这并不重要。
ChildView
中可能存在需要动画化的更改,或者需要运行的
onDisappear
等。

至于

body
的调用顺序,是从父级到子级。您可以通过在
let _ = print("...")
中放置一些
body
语句来看到这一点。

旁注:您可以使用

objectWillChange
属性包装器来包装
buttonText
,而不是发送
@Published

© www.soinside.com 2019 - 2024. All rights reserved.