【问题标题】:Change to @Published var in @EnvironmentObject not reflected immediately更改为 @EnvironmentObject 中的 @Published var 不会立即反映
【发布时间】:2019-08-15 15:09:56
【问题描述】:

在这种特定情况下,当我尝试更改@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 是 Modal 中的 @State var,则此方法有效。如果它是 @State varMasterView 内,@Binding varModal 内,它也可以工作。它只是不适用于此设置。

【问题讨论】:

  • 可能我也有同样的问题。当我删除 willSet 以支持 Published 时,某些东西不再起作用
  • @GiuseppeSapienza,看看我的回答,看看它是否对你有帮助。在 beta 5 更新 List 之后,我遇到了一个问题,这解决了它。
  • @dfd 感谢现在正在工作(ps iOS 13 beta 7 几分钟前发布)
  • @GiuseppeSapienza,很高兴为您提供帮助。这是我第一次参与测试版。当上周发布 iOS beta 6(现在是 beta 7?)时,我感到很惊讶,但我一直想知道 Xcode beta 6 不是每两周安排一次(像其他人一样),或者他们是否遇到了一些问题。 SwiftUI 和/或 Combine 更改似乎无缘无故发生的速度令人沮丧。这个?如果 iOS beta 7 修复了它,Xcode beta 6 修复了它,或者它的预期行为应该会很有趣。
  • @dfd 我认为这很正常,就像苹果发布 Swift 时,他们在每个版本中都改变了很多东西。无论如何似乎最后一个测试版(Xcode beta 7)并没有解决这个问题

标签: swiftui


【解决方案1】:

几件事。

  • 如果您将 Button 移到 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()
        }
    }
}

我测试了一些东西,它可以工作。

【讨论】:

    【解决方案2】:

    变化

    final class UserData: NSObject, ObservableObject  {
    

    final class UserData: ObservableObject  {
    

    确实修复了 Xcode11 Beta6 中的问题。 SwiftUI 似乎没有正确处理实现ObservableObjectNSObject 子类(至少它似乎没有调用它的内部willSet 块)。

    【讨论】:

    • 非常好,好评!我已经接受了 beta 5 的答案(我认为,这是一个移动的目标),但没有尝试以任何方式删除 NSObject。嘿,我的代码有效——这一次,这是一件大事!现在,如果我只能找到一种方法来通过UIViewControllRepresentable UIButton 点击​​更新我的环境对象......(@Fabian,你似乎是最好的之一 - 如果你能做到这一点,我会发布一个问题。一直尝试了几天。)
    • 环境对象是否正在更新,并且只是使用未调用的数据更新视图?无论如何,我看不到新问题与NSObject 的问题之间的联系。那里的环境对象是否也使用NSObject
    • 它正在更新。完整的描述是我有一个UINavigationController,堆栈中有两个UIViewControllers,有点像主细节。我需要 (a) 在导航栏中有一个 AddEdit 按钮,并且我已经可以更新/编辑绑定到模型的表格视图。显然需要更新状态的是添加按钮。实际上,我会在“纯”SwiftUI 中执行此操作,但现在有太多痛点,所以我希望通过点击按钮在我的模型中触发某些东西....继续....
    • 这是我今天早些时候发布的问题:这是我的问题:stackoverflow.com/questions/57676251/…
    【解决方案3】:

    在 Xcode 11 GM2 中,如果您已覆盖 objectWillChange,则需要在已发布变量的 setter 上调用 send()

    如果你不覆盖objectWillChange,一旦@EnvironmentObject 或@ObservedObject 中发布的变量发生变化,视图应该被刷新。由于在 Xcode 11 GM2 objectWillChange 中已经有一个默认实例,因此不再需要在 ObservableObject 中提供它。

    【讨论】:

    • 这是正确答案。在几乎所有情况下,只需删除您自己的 objectWillChange 声明,就无需再在 willSet@Published 属性中手动调用 objectWillChange.send()
    猜你喜欢
    • 2016-04-27
    • 2021-12-12
    相关资源
    最近更新 更多