I need to fetch some data from Firestore, process them, and present them to a view.
The data should reflect any changes in Firestore (say I alter a value).
I am pretty sure I need to attach a snapshotListener for this (getDocuments() method will not cut it).
Today I found out about @FirestoreQuery property wrapper (which is very helpful) but I need to find a way to make this work asynchronously.
Before fixing my code I used getDocuments(...) and I could easily use the async await like so:
func fetchAllItems() async throws -> [Item] {
let snapshot = try await Firestore.firestore().collection("items").getDocuments()
return snapshot.documents.compactMap { document in
try? document.data(as: Item.self)
}
}
Inside the View, I use the following:
.onAppear {
Task.init {
self.items = try await fetchAllItems()
}
}
The code above worked just fine, but I couldn't see the changes on my app, unless I reloaded the app to force calling Firestore again.
Is there a way to replicate this but with either addSnapshotListener
or @FirestoreQuery
?
Can this be marked as try await
or is it any other way to wait for the data to download? Cause if I use it as below, it returns an empty array:
@FirestoreQuery(collectionPath: "items") var items: [Item]
Edit: Code samples
import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift
extension Firestore {
func fetchAllItems() async throws -> [Item] {
let snapshot = try await Firestore.firestore().collection("items").getDocuments()
return snapshot.documents.compactMap { document in
try? document.data(as: Item.self)
}
}
}
Then inside my View:
import SwiftUI
import FirebaseFirestore
.
.
@State var allItems: [Item] = []
.onAppear {
Task.init {
self.allItems = try await Firestore.firestore().fetchAllItems()
}
}
Above code will work and receive data from Firestore just fine.
If I remove the async/await nature and go with the @FirestoreQuery then it will not receive the data (I assume that it has to do with the View loading faster than receiving the data from Firestore).
Thank you in advance!
[I am using SwiftUI]