在@EnvironmentObject 中对@Published var 的更改不会立即反映出来
Change to @Published var in @EnvironmentObject not reflected immediately
在这种特定情况下,当我尝试更改 @EnvironmentObject
的 @Published var
时,我发现视图没有失效并立即更新。相反,对变量的更改仅在离开模态并返回后才会反映出来。
import SwiftUI
final class UserData: NSObject, ObservableObject {
@Published var changeView: Bool = false
}
struct MasterView: View {
@EnvironmentObject var userData: UserData
@State var showModal: Bool = false
var body: some View {
Button(action: { self.showModal.toggle() }) {
Text("Open Modal")
}.sheet(isPresented: $showModal, content: {
Modal(showModal: self.$showModal)
.environmentObject(self.userData)
} )
}
}
struct Modal: View {
@EnvironmentObject var userData: UserData
@Binding var showModal: Bool
var body: some View {
VStack {
if userData.changeView {
Text("The view has changed")
} else {
Button(action: { self.userData.changeView.toggle() }) {
Text("Change View")
}
}
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
MasterView().environmentObject(UserData())
}
}
#endif
这是一个错误还是我做错了什么?
如果 changeView
是模态框内的 @State var
,则此方法有效。如果它是 MasterView
内的 @State var
和 Modal
内的 @Binding var
,它也有效。它只是不适用于此设置。
几件事。
- 如果您将按钮移至
MasterView
,您的设置将不起作用。
- 您的代码中没有
import Combine
(别担心,单独 没有帮助)。
这是解决方法。我不知道这是一个错误,还是文档不完善——IIRC 指出 objectWillChange
是隐含的。
在将 import Combine
添加到代码中的同时,将 UserData
更改为:
final class UserData: NSObject, ObservableObject {
var objectWillChange = PassthroughSubject<Void, Never>()
@Published var changeView: Bool = false {
willSet {
objectWillChange.send()
}
}
}
我测试了一些东西并且它有效。
改变
final class UserData: NSObject, ObservableObject {
到
final class UserData: ObservableObject {
确实修复了 Xcode11 Beta6 中的问题。 SwiftUI 似乎没有正确处理 NSObject
实现 ObservableObject
的子类(至少它似乎没有调用它的内部 willSet
块)。
在Xcode 11 GM2中,如果你覆盖了objectWillChange
,那么它需要在setter上调用send()
发布的变量。
如果不覆盖objectWillChange
,一旦@EnvironmentObject 或@ObservedObject 中发布的变量发生变化,视图应该被刷新。由于在Xcode 11 GM2 objectWillChange
中已经有一个默认实例,因此不再需要在ObservableObject
.
中提供它
在这种特定情况下,当我尝试更改 @EnvironmentObject
的 @Published var
时,我发现视图没有失效并立即更新。相反,对变量的更改仅在离开模态并返回后才会反映出来。
import SwiftUI
final class UserData: NSObject, ObservableObject {
@Published var changeView: Bool = false
}
struct MasterView: View {
@EnvironmentObject var userData: UserData
@State var showModal: Bool = false
var body: some View {
Button(action: { self.showModal.toggle() }) {
Text("Open Modal")
}.sheet(isPresented: $showModal, content: {
Modal(showModal: self.$showModal)
.environmentObject(self.userData)
} )
}
}
struct Modal: View {
@EnvironmentObject var userData: UserData
@Binding var showModal: Bool
var body: some View {
VStack {
if userData.changeView {
Text("The view has changed")
} else {
Button(action: { self.userData.changeView.toggle() }) {
Text("Change View")
}
}
}
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
MasterView().environmentObject(UserData())
}
}
#endif
这是一个错误还是我做错了什么?
如果 changeView
是模态框内的 @State var
,则此方法有效。如果它是 MasterView
内的 @State var
和 Modal
内的 @Binding var
,它也有效。它只是不适用于此设置。
几件事。
- 如果您将按钮移至
MasterView
,您的设置将不起作用。 - 您的代码中没有
import Combine
(别担心,单独 没有帮助)。
这是解决方法。我不知道这是一个错误,还是文档不完善——IIRC 指出 objectWillChange
是隐含的。
在将 import Combine
添加到代码中的同时,将 UserData
更改为:
final class UserData: NSObject, ObservableObject {
var objectWillChange = PassthroughSubject<Void, Never>()
@Published var changeView: Bool = false {
willSet {
objectWillChange.send()
}
}
}
我测试了一些东西并且它有效。
改变
final class UserData: NSObject, ObservableObject {
到
final class UserData: ObservableObject {
确实修复了 Xcode11 Beta6 中的问题。 SwiftUI 似乎没有正确处理 NSObject
实现 ObservableObject
的子类(至少它似乎没有调用它的内部 willSet
块)。
在Xcode 11 GM2中,如果你覆盖了objectWillChange
,那么它需要在setter上调用send()
发布的变量。
如果不覆盖objectWillChange
,一旦@EnvironmentObject 或@ObservedObject 中发布的变量发生变化,视图应该被刷新。由于在Xcode 11 GM2 objectWillChange
中已经有一个默认实例,因此不再需要在ObservableObject
.