I am trying to avoid unnecessary reads on my FireStore database by filtering my SnapshotListener
with lastDatesCheck
: A date value which I update and store inside my app (UserDefaults) each time when I successfully fired the query.
In my FireStore-documents I have a lastModified
field which I compare lastDatesCheck
with.
I am trying to get unchanged data from cache and only changes from server.
Do I have to use Swifts CoreData
to save my old datesArray
, or can I get the cache plus the updates out of the same FireStore-Snapshot?
This is my code which produces an empty datesArray
from 2nd app-start on, because the listener doesn't find anything anymore fitting to the lastDatesCheck
-filter. This makes sense, but how do I fill my datesArray
from cache now?
@AppStorage("lastDatesCheck") var lastDatesCheck: Date = Date(timeIntervalSinceNow: -365 * 24 * 60 * 60)
@Published var datesArray: [DateModel] = []
struct DateModel: Identifiable, Hashable {
var id: Int
var documentId: String
var startDate: Date
var endDate: Date?
var title: String
var homepage: String?
}
func listen(completion: @escaping () -> Void) {
let db = Firestore.firestore()
listenerDates = db.collection("dates")
.whereField("lastModified", isGreaterThanOrEqualTo: lastDatesCheck)
.addSnapshotListener { (snapshot, error) in
guard let snapshot = snapshot else {
print(error!.localizedDescription)
DispatchQueue.main.async {
completion()
return
}
return
}
snapshot.documentChanges.forEach { diff in
if (diff.type == .added) {
print("New Data: \(diff.document.data())")
}
if (diff.type == .modified) {
print("Modified Data: \(diff.document.data())")
}
if (diff.type == .removed) {
print("Removed Data: \(diff.document.data())")
}
}
let source = snapshot.metadata.isFromCache ? "local cache" : "server"
print("Metadata: Data fetched from \(source)")
self.datesArray.removeAll()
for document in snapshot.documents {
if let title = document.get("title") as? String {
if let startDate = document.get("startDate") as? Timestamp {
let startDatefromDb = startDate.dateValue()
let endDate: Timestamp? = document.get("endDate") as? Timestamp ?? nil
let homepage: String? = document.get("homepage") as? String ?? nil
let endDatefromDb: Date? = endDate?.dateValue()
let currentIndex = self.datesArray.last?.id
let newDate = DateModel(id: (currentIndex ?? -1)+1, documentId: document.documentID, startDate: startDatefromDb, endDate: endDatefromDb, title: title, homepage: homepage)
self.datesArray.append(newDate)
}
}
}
DispatchQueue.main.async {
self.lastDatesCheck = Date()
completion()
return
}
}
}