观察对象更改时,Swift View 不更新

Posted

技术标签:

【中文标题】观察对象更改时,Swift View 不更新【英文标题】:Swift View not updating when Observed Object changes 【发布时间】:2020-05-02 13:45:26 【问题描述】:

我有一些这样的代码:

class Data: ObservableObject 
 @Published var data = dbContent

 init()
  let db = Firestore.firestore()
  db.collection("collection").document(userID).addSnapshotListener 
  //getting data from DB and storing them as objects by appending them to data
  
 

struct 1View: View 
 @ObservedObject var myData: Data = Data()

 var body: some View 
  2View(myData: self.myData)
  3View(myData: self.myData)
 

struct 2View: View 
 @State var myData: Data

 var body: some View 
  List()
   ForEach(data.count) data in
    Text(data)
   .onDelete(perform: deleteData) //Deletes the item
  
 

struct 3View: View 
 @State var myData: Data

 var body: some View 
  List()
   ForEach(data.count) data in
    Text(data)
   .onDelete(perform: deleteData) //Deletes the item
  
 

现在的问题是,我可以删除 2View 中的项目。然后也显示了这一点,并且我实现了它也删除数据库中的项目的功能。 所以数据库数据被改变了,但在我通过例如刷新它之前,这不会显示在 3View 中。重新审视它。

我不知道是什么原因。也许我对 @PublishedObservedObject 有错误的理解?

【问题讨论】:

您分配了 dbContent 吗? dbContent 被我在从数据库中获取数据时创建的自定义对象“覆盖”。也许这就是错误所在?我在这个方法中有一个snapshotListener,这个方法的目标是将新创建的对象分配给dbContent。像这样工作吗? 【参考方案1】:

@State 表示视图拥有数据并管理状态。尝试在您的子视图中使用@ObservedObject。这是一个例子:

型号

struct Book: Codable, Identifiable 
  @DocumentID var id: String?
  var title: String
  var author: String
  var numberOfPages: Int

  enum CodingKeys: String, CodingKey 
    case id
    case title
    case author
    case numberOfPages = "pages"
  

视图模型

class BooksViewModel: ObservableObject 
  @Published var books = [Book]()

  private var db = Firestore.firestore()
  private var listenerRegistration: ListenerRegistration?

  private var cancellables = Set<AnyCancellable>()

  init() 
    fetchData()
  

  deinit 
    unregister()
  

  func unregister() 
    if listenerRegistration != nil 
      listenerRegistration?.remove()
    
  

  func fetchData() 
    unregister()

    listenerRegistration = db.collection("books").addSnapshotListener  (querySnapshot, error) in
      guard let documents = querySnapshot?.documents else 
        print("No documents")
        return
      

      self.books = documents.compactMap  queryDocumentSnapshot -> Book? in
        return try? queryDocumentSnapshot.data(as: Book.self)
      
    
  

  func deleteBooks(at offsets: IndexSet) 
    self.books.remove(atOffsets: offsets)
  



观看次数

import SwiftUI

struct SampleView: View 
  @ObservedObject var viewModel = BooksViewModel()

  var body: some View 
    VStack 
      InnerListView1(viewModel: viewModel)
      InnerListView2(viewModel: viewModel)
    
  


struct InnerListView1: View 
  @ObservedObject var viewModel: BooksViewModel

  var body: some View 
    List 
      ForEach(viewModel.books)  book in
        VStack(alignment: .leading) 
          Text(book.title)
            .font(.headline)
          Text(book.author)
            .font(.subheadline)
          Text("\(book.numberOfPages) pages")
            .font(.subheadline)
        
      
      .onDelete  indexSet in
        self.viewModel.deleteBooks(at: indexSet)
      
    
  




struct InnerListView2: View 
  @ObservedObject var viewModel: BooksViewModel

  var body: some View 
      List(viewModel.books)  book in
        VStack(alignment: .leading) 
          Text(book.title)
            .font(.headline)
          Text(book.author)
            .font(.subheadline)
          Text("\(book.numberOfPages) pages")
            .font(.subheadline)
      
    
  

我在尝试重现您的问题时注意到的一件事:如果您使用的是 CodingKeys(只有在 Firestore 文档上的属性名称与 Swift 结构上的属性名称不同时才需要这样做),您需要确保id 也包括在内。否则,id 将为 nil,这将导致 List 视图无法区分项目。

【讨论】:

遗憾的是,这并没有成功。但是感谢您的努力! @Simon,我已经扩展了示例 - 请再试一次。我刚刚尝试过,它按预期工作。

以上是关于观察对象更改时,Swift View 不更新的主要内容,如果未能解决你的问题,请参考以下文章

Swift Struct 实例在更新其值时发生更改

可观察对象模型在模型更新时不会更改视图值

基于设备旋转更新变量 - Swift UI

Swift Firestore 来自查询的自定义对象,同时使用 snapshotListener 监听实时更新

不应发生的 Swift 内存冲突

SwiftUI - 从 Swift 类启动的可观察对象不会更新 ContentView() 上的 @ObservedObject