【问题标题】:Unable to update Published var from Class无法从 Class 更新 Published var
【发布时间】:2021-08-07 02:43:38
【问题描述】:

我有一个已发布的 var prediction:

class TrainingStatus: ObservableObject {
    @Published var isTrained: Bool = false
    @Published var modelUrl: URL = URL(fileURLWithPath: "hello")
    @Published var prediction:String = ""
}

我尝试在一个类中更新这个变量:

class ClassificationController: ObservableObject {
...
 func processObservations(for request: VNRequest, error: Error?) {
      DispatchQueue.main.async {
        if let results = request.results as? [VNClassificationObservation] {
          if results.isEmpty {
            print("nothing found")
          } else {
              print("got a result: \(results)!")
              let top3 = results.prefix(3).map { observation in
                String(format: "%@ %.1f%%", observation.identifier, observation.confidence * 100)
              }
              self.prediction = top3.joined(separator: " ")
              
              // attempt to set environment variable?
              let trainingStatus = TrainingStatus()
              trainingStatus.prediction = self.prediction
              
              print("set prediction: \(trainingStatus.prediction)")
          }
}

并在我的 UIView 中显示这个变量:

struct SidebarView: View {
   
    @EnvironmentObject var trainingStatus: TrainingStatus
 
    
    var body: some View {
        VStack{
            NavigationView{
                    Section{
                        Text("Trained? " + String(trainingStatus.isTrained))
                        Text("Prediction: \(trainingStatus.prediction)")
                    }
                    
                }
                .navigationTitle("Data")
            }
            .environmentObject(modelData)
            .environmentObject(trainingStatus)
        }
    }
}

但是,尽管 prediction 的值似乎在 ClassificationController 中更新,但我的带有文本 \(trainingStatus.prediction) 的 UI 视图从未更新。

如何更新视图以获取最新发布的值?

【问题讨论】:

  • 如您所见,您不能这样做:let trainingStatus = TrainingStatus() trainingStatus.prediction = self.prediction。阅读更多关于如何使用 ObservableObject 以及如何传递它们的信息。您想要实现的是仅使用 1 个 TrainingStatus。
  • @workingdog 你能推荐一些关于如何正确设置可观察对象的资源吗?

标签: swift swiftui


【解决方案1】:

您可以有效地利用(几乎)单例。

您首先需要更改 ObservableObject 类并添加一个新常量:

     class TrainingStatus: ObservableObject {
        @Published var isTrained: Bool = false
        @Published var modelUrl: URL = URL(fileURLWithPath: "hello")
        @Published var prediction:String = ""

        public static let shared = TrainingStatus()
    }

然后您可以通过声明以下内容在其他地方访问它:

var trainingStatus = TrainingStatus.shared

现在您可以随意修改它的值。这也将在 ObservableObject 类中更新它,因此在任何其他使用它的视图中更改它。

您的用例示例:

 struct SidebarView: View {
   
    var trainingStatus = TrainingStatus.shared
 
    
    var body: some View {
        VStack{
            NavigationView{
                    Section{
                        Text("Trained? " + String(trainingStatus.isTrained))
                        Text("Prediction: \(trainingStatus.prediction)") //This is now referencing your new shared variable of trainingStatus
                    }
                    
                }
                .navigationTitle("Data")
            }
            .environmentObject(modelData)
            .environmentObject(trainingStatus)
        }
    }
}

要修改常量的类:

 class ClassificationController: ObservableObject {
 
 var trainingStatus = TrainingStatus.shared

...
 func processObservations(for request: VNRequest, error: Error?) {
      DispatchQueue.main.async {
        if let results = request.results as? [VNClassificationObservation] {
          if results.isEmpty {
            print("nothing found")
          } else {
              print("got a result: \(results)!")
              let top3 = results.prefix(3).map { observation in
                String(format: "%@ %.1f%%", observation.identifier, observation.confidence * 100)
              }
              self.prediction = top3.joined(separator: " ")
              
              // attempt to set environment variable?
              //let trainingStatus = TrainingStatus() --- no longer need this line
              trainingStatus.prediction = self.prediction //this is now changing your singleton
              
              print("set prediction: \(trainingStatus.prediction)")
          }
}

【讨论】:

  • 已编辑以在您提供的代码中添加示例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-29
  • 1970-01-01
  • 2021-04-21
  • 2021-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多