【问题标题】:ObservedObject not triggering view redrawObservedObject 未触发视图重绘
【发布时间】:2020-10-01 14:10:31
【问题描述】:

我有一个需要从 api 获取数据的视图。 我对 SwiftUI 的理解是,通过使用 onAppear,将调用 api,更新 viewmodel 属性,并更改 StateObject,这将触发 View 重绘。

问题是没有进行重绘。

我可以看到一个api调用发生了,并且在使用解码数据后添加调试我可以看到返回了很多数据。

我删除了很多代码以使逻辑更易于理解(如下)。

用@ObservedObject 替换@StateObject 并从父级传递到视图中也没有区别。

谢谢

struct FactoryDetailView: View {

  var factory: Factory
  @StateObject var factoryDetailsViewModel: FactoryDetailsViewModel()

  var body: some View {

     VStack {
        Text(factory.name)
        ForEach(factoryDetailsViewModel.details) { det in
          Text(det)
        }
     }
     .onAppear { factoryDetailsViewModel.loadDetails(factory) }
  }
}

视图模型:

class FactoryDetailsViewModel: ApiViewModel {
  @Published var details: [ String ]
  func loadDetails(factory: Factory) {

     // Do api call...

     self.objectWillChange.send()
     self.details = decodedResultsFromApiCall
     self.objectWillChange.send()
}
class ApiViewModel: ObservableObject {
}

【问题讨论】:

    标签: swiftui publish observableobject


    【解决方案1】:

    嗯...删除的细节可能是问题的原因,但一般方法应该如下所示

    struct FactoryDetailView: View {
      ...
      // assume it is a type and here there is initialization 
      @StateObject var factoryDetailsViewModel = FactoryDetailsViewModel()
      ...
    

    现在关于self.objectWillChange.send() - 不要调用它,修改发布的属性它会自动调用

    func loadDetails(factory: Factory) {
    
         // Do api call...
         { 
              // this is inside (!) API callback
              DispatchQueue.main.async {
                 // update published property on main queue, always.
                 self.details = decodedResultsFromApiCall
              }
         }
    }
    

    【讨论】:

    • 谢谢。我刚刚发现,如果我删除 '@Published' 它可以工作,但需要 objectWillChange.send() 调用。我猜在某些情况下您不能使用“@Published”包装器。我试图避免手动调用 objectWillChange,因为这似乎违背了它应该完成的方式。
    【解决方案2】:

    这有答案:

    @Published property wrapper not working on subclass of ObservableObject

    我看到的问题是相同的 - 子类化 ObservableObject。

    我现在有了一个解决方案,通过父类中的“@Published var api_response”并从子类的属性中删除@Published(尽管在其中留下“@Published”似乎不会造成任何副作用,所以它们如果只是为了记录意图,也可以保留)。

    感谢您的回复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-21
      • 1970-01-01
      • 2020-07-12
      • 2021-02-17
      • 2020-05-02
      相关资源
      最近更新 更多