0

I have some code like this:

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

Now the issue is, that I can delete the the item in the 2View. This is then also shown and I implemented the functionality that it deletes the Item in the DB as well. So the DB data gets altered but this is not shown in the 3View until I refresh it by e.g. revisiting it.

I have no idea what the cause is. Maybe I got a wrong understanding of @Published and ObservedObject ?

2
  • Did you assign dbContent? Commented May 2, 2020 at 16:18
  • dbContent gets "overwritten" by the custom object that I create when getting the data from the Database. Maybe here lies the error? I have a snapshotListener in this method and the goal of this method is to assign the newly created object to dbContent. Does this work like that? Commented May 3, 2020 at 9:32

1 Answer 1

2

@State means that the view owns the data and manages the state. Try using @ObservedObject in your child views as well. Here is an example:

Model

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) } } 

Views

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) } } } } 

One thing I noticed when trying to reproduce your issue: if you're using CodingKeys (which you only need to do if your the attribute names on the Firestore documents are different from the attribute names on your Swift structs), you need to make sure that the id is also included. Otherwise, id will be nil, which will result in the List view not being abel to tell the items apart.

Sign up to request clarification or add additional context in comments.

2 Comments

Sadly this did not do the trick. But thank you for the efforts!
@Simon, I've expanded the sample - please give it another try. I've just tried this, and it works as intended.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.