如果您要将@EnvironmentObject
传递给以工作表形式显示的视图,您会注意到,@Published
中的任何@EnvironmentObject
属性每次更新时都会重新创建此工作表
展示问题的最小示例:
import SwiftUI
class Store: ObservableObject {
@Published var name = "Kevin"
@Published var age = 38
}
struct ContentView: View {
@EnvironmentObject private var store: Store
@State private var showProfile = false
var body: some View {
VStack {
Text("Hello, \(store.name), you're \(store.age) years old")
Button("Edit profile") {
self.showProfile = true
}
}
.sheet(isPresented: $showProfile) {
ProfileView()
.environmentObject(self.store)
}
}
}
struct ProfileView: View {
@EnvironmentObject private var store: Store
@ObservedObject private var viewModel = ViewModel()
var body: some View {
VStack {
Text("Hello, \(store.name), you're \(store.age) years old")
Button("Change age") {
self.store.age += 1
}
}
}
}
class ViewModel: ObservableObject {
init() {
print("HERE")
}
}
如果运行此代码,您会发现每按一次表单中的按钮,就会记录一次“ HERE”,这意味着重新创建了ViewModel
。您可能会想象到,这可能是一个巨大的问题,我希望不会重新创建ViewModel,而是保留其状态。这在我的应用程序中引起了巨大的问题。
据我所知,我在代码中执行的操作是将@EnvironmentObject
传递到工作表的常规方法。有没有一种方法可以防止ProfileView
中的任何更改重新创建Store
?
答案 0 :(得分:1)
这是因为当状态变量更改时,会重新创建视图。然后在您的视图中将viewModel实例化为ViewModel()。
尝试将观察到的对象作为参数传递,它将不再命中“ HERE”:
struct ContentView: View {
@EnvironmentObject private var store: Store
@State private var showProfile = false
@ObservedObject private var viewModel = ViewModel()
var body: some View {
VStack {
Text("Hello, \(store.name), you're \(store.age) years old")
Button("Edit profile") {
self.showProfile = true
}
}
.sheet(isPresented: $showProfile) {
ProfileView(viewModel: self.viewModel)
.environmentObject(self.store)
}
}
}
struct ProfileView: View {
@EnvironmentObject private var store: Store
@ObservedObject var viewModel: ViewModel
var body: some View {
VStack {
Text("Hello, \(store.name), you're \(store.age) years old")
Button("Change age") {
self.store.age += 1
}
}
}
}
答案 1 :(得分:0)
一篇关于这个问题的非常好的文章can be found her。