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

时间:2020-05-02 13:45:26

标签: swift firebase google-cloud-firestore swiftui

我有一些这样的代码:

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中的项目。然后也显示了这一点,我实现了删除数据库中Item的功能。 所以数据库数据被更改了,但是直到我通过例如重新访问它。

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

1 个答案:

答案 0 :(得分:2)

@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"
  }
}

ViewModel

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视图无法区分这些项目。

相关问题