在@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 varModal 内的 @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.

中提供它