繁体   English   中英

SwiftUI EnvironmentObject 不会重绘当前视图,而是重绘其父视图

[英]SwiftUI EnvironmentObject does not redraw the current view but its parent view

我试图了解@EnvironmentObjectObservableObject中的属性更改时如何影响重绘。

根据 Apple 关于EnvironmentObject的文档,

每当可观察对象发生变化时,环境对象都会使当前视图无效。

如果上述陈述为真,那么当您按下ContentView中的按钮时,下面的代码不会使ChildView失效并重新创建。 这应该打印以下输出。

initializing parent
initializing child
// after pressing the button
initializing child 

与我的上述假设相反,它实际上打印

initializing parent
initializing child
// after pressing the button
initializing parent 

谁能解释为什么会这样? 为什么ParentView被重新创建,即使ParentView不依赖于Library

class Library: ObservableObject {
  @Published var item: Int = 0
}

struct ContentView: View {
  @StateObject var library: Library = Library()
  var body: some View {
    VStack {
      ParentView()
        .environmentObject(library)
      Button {
        library.item += 1
      } label: {
        Text("increment")
      }
    }
  }
}

struct ParentView: View {
  init() {
    print("initializing parent")
  }
  var body: some View {
    VStack {
      Text("Parent view")
      ChildView()
    }
  }
}

struct ChildView: View {
  @EnvironmentObject var library: Library
  init() {
    print("initializing child")
  }
  var body: some View {
    Text("Child view")
  }
}

SwiftUI View 可能有点棘手。

每当可观察对象发生变化时,环境对象都会使当前视图无效。

并不意味着对象本身被重新创建。 它只是意味着视图的主体被调用并且视图自身重建。

请记住,结构不是View本身,它只是一个“描述”。

我添加了一些打印语句以使这一点更清楚:

struct ContentView: View {
    @StateObject var library: Library = Library()
    
    init(){
        print("initializing content")
    }
    
    var body: some View {
        VStack {
            let _ = print("content body")
            ParentView()
                .environmentObject(library)
            Button {
                library.item += 1
            } label: {
                Text("increment")
            }
        }
    }
}

struct ParentView: View {
    init() {
        print("initializing parent")
    }
    var body: some View {
        VStack {
            let _ = print("parent body")
            Text("Parent view")
            ChildView()
            
        }
    }
}

struct ChildView: View {
    @EnvironmentObject var library: Library
    init() {
        print("initializing child")
    }
    var body: some View {
        let _ = print("child body")
        Text("child")
    }
}

这最初打印:

initializing content
content body
initializing parent
parent body
initializing child
child body

按下按钮后:

content body
initializing parent
child body

正如您所见,这些View的主体取决于Library ,它们各自的主体被重新评估。

ParentView初始化程序运行是因为在您的ContentView中,您在正文中调用ParentView() ,因此创建了一个“描述”您的 View 的新结构。 ParentView的视图本身保持不变,因此不会调用其body var。

这个关于 SwiftUI 视图的WWDC 2021视频将帮助您更好地理解这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM