SwiftUI - 环境对象未更新UI

5
我的应用程序有一个按钮,可以产生绿色或红色的背景。用户按下按钮多次以生成每次的绿色或红色,并将结果记录到名为“当前会话”的Observable对象中。当前总数显示在由胶囊制成的自定义视图中。由于某种原因,视图不会更新总数并继续显示0。
我尝试为ResultsBar中的numberOfGreens添加状态绑定,但这也不起作用。它仍然每次都只显示0。环境已经添加到我的所有视图中。我尝试打印结果,结果数字在控制台中正确显示,但UI不会更新。有趣的是,在我的应用程序的其他屏幕上,trialsRemaining变量完美地工作,更新时没有任何问题。另外,在预览中,ResultsBar也完全正常。
class CurrentSession: ObservableObject {

  @Published var trialsRemaining: Int = 100
  @Published var numberOfGreens: Int = 0
  @Published var numberOfReds: Int = 0

  func generateGreenOrRed() {
    ...
    if resultIsGreen {numberOfGreens += 1}
    else if resultIsRed {numberOfReds += 1}
    trialsRemaining -= 1
  }
}

struct ResultsBar: View {
  let totalBarWidth: CGFloat = UIScreen.main.bounds.width - 48
  var onePercentOfTotalWidth: CGFloat { return totalBarWidth/100 }
  var numberOfGreens: Int

  var body: some View {
    ZStack(alignment: .leading) {       
      Capsule()
        .frame(width: totalBarWidth, height: 36)
        .foregroundColor(.red)
        .shadow(radius: 4)   
      Capsule()
        .frame(width: (onePercentOfTotalWidth * CGFloat(numberOfGreens)), height: 36)
        .foregroundColor(.green)
        .shadow(radius: 4)   
    }
  }
}

struct ResultsView: View {

  @EnvironmentObject var session: CurrentSession

  var body: some View {
    VStack {       
      HStack {
        Text("\(session.numberOfGreens)")
        Spacer()
        Text("\(session.numberOfReds)")       
      }

      ResultsBar(numberOfGreens: session.numberOfGreens)
    }
  }
}

我正在运行的是Xcode 11.2 beta 2 (11B44),在macOS Catalina 10.15.2 Beta (19C32e)上。


你能展示一下按钮的代码吗? - Chris
@Chris,除了一个调用生成绿色或红色的函数并设置计时器以在五秒钟内禁用按钮的buttonPressed函数外,实际上没有什么内容(所有这些都正常工作)。 - brianwantsblood
2个回答

5
您是否将对 "CurrentSession" 实例的引用传递给您的 "ResultsView"?如果我复制您的代码,当我单击它时,以下内容确实会更新 "ResultsBar"。
struct ContentView: View {
    @ObservedObject var session = CurrentSession()

    var body: some View {
        ResultsView()
            .environmentObject(session)
            .onTapGesture {
                self.session.generateGreenOrRed()
            }
    }
}

2
这让我解决了问题!并不是你说的那样,而是关于使用EnvironmentObject包装器。我将其改为ObservedObject,并在视图主体末尾添加环境对象,现在它可以正常工作了。感谢你引导我走向正确的方向。 - brianwantsblood
在iOS 14中,这个解决方案会破坏应用程序,请不要这样做!!! - Hattori Hanzō

3

我遇到了同样的问题,但是我的问题是因为我在后台线程上更新环境对象,因为我正在使用一个api。为了解决我的问题,我只需要像下面这样包装设置EnvironmentObject变量即可。

DispatchQueue.main.async{
    self.numberOfGreens = GetNumberOfGreens(id: id)
}

我希望这能对某些人有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接