Swift View не обновляется при изменении наблюдаемого объекта - PullRequest
0 голосов
/ 02 мая 2020

У меня есть такой код:

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, пока я не обновлю sh, например, вернувшись к нему.

Понятия не имею, в чем причина. Может быть, я неправильно понял @Published и ObservedObject?

1 Ответ

1 голос
/ 02 мая 2020

@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 будет равен нулю, что приведет к тому, что представление List не сможет различать элементы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...