My app uses Firebase to sync and restore data. I use the setValue:withCompletionBlock:
method to insert, update and delete Firebase objects. This method is called whenever there is a CoreData save, thus syncing all my local changes to Firebase
- (void) setValue:(id)value withCompletionBlock:(void (^)(NSError* error, Firebase* ref))block;
Now syncing uploads all the local data to firebase, while restore replaces the local data with firebase data.
- (void) observeSingleEventOfType:(FEventType)eventType withBlock:(void (^)(FDataSnapshot* snapshot))block;
I observe FEventTypeValue
and use the FDataSnapshot
to get data from the Firebase and restore the local data.
So everything works perfectly for me until I set persistence
to Firebase.
[Firebase setOption:@"persistence" to:@YES];
Now when persistence
is on, when I update, say insert an object into Firebase, and then restore, the data before the insertion is restored. ie the newly inserted object is not restored. However if I restore again, the inserted object is restored. The same thing happens when an object is deleted. The deleted object reappears when I restore for the first time and vanishes when I restore again. I can see that the Firebase objects are inserted and/or deleted correctly through the Firebase data view.
I'm not sure what I'm doing wrong here. I only have issue when I restore. I think the Firebase cache is causing this restore issue. I'm thinking of clearing the Firebase cache before I restore. My question is
There's no API for manipulating the local cache in any way. The Firestore SDK chooses what to store based on queries that you perform. On Android, users can manually clear the local data for an app without uninstalling it. This will remove all the data locally stored by the app.
Note: Offline persistence is supported only in Android, Apple, and web apps. To use offline persistence, you don't need to make any changes to the code that you use to access Cloud Firestore data.
Firebase Hosting uses a powerful global CDN to make your site as fast as possible. Any requested static content is automatically cached on the CDN. If you redeploy your site's content, Firebase Hosting automatically clears all your cached static content across the CDN until the next request.
By enabling persistence, any data that the Firebase Realtime Database client would sync while online persists to disk and is available offline, even when the user or operating system restarts the app. This means your app works as it would online by using the local data stored in the cache.
[NOTE: If using Cloud Firestore instead of Realtime Database is an option for you, it has much better offline support. When you do a .get(), it will automatically attempt to fetch the latest data from the server and only use cached data if you are offline. You can also specifically request to retrieve data from either the server or cache.]
This is unfortunately expected behaviour. You can probably work around it by using observeEventOfType instead of observeSingleEventOfType
Basically, whenever you observe data, we're going to pull data from our persistent cache first. That data will be whatever data we last received from Firebase. Because you're using observeSingleEventOfType instead of observeEventOfType, you're not going to be receiving regular updates from Firebase and so the data we have cached actually won't include the latest data that you wrote.
As a simple fix, you may be able to just add an observeEventOfType on the data in question. You don't actually need to do anything with the events. But if you listen to them all the time, then your app will be getting the latest data from firebase and when you call observeSingleEventOfType, you can be confident that it'll have the latest data cached.
You can use the snap.metadata.fromCache
flag to check if the value is coming from the cache or not. Note that if the cache value and the value from the server match it won't fire your onSnapshot twice unless you add the includeMetadataChanges
flag seen below, instead it would only fire it once with the metadata.fromCache
flag being set to true
.
db.collection('users').doc(uid).onSnapshot({ includeMetadataChanges: true }, (snap) => { if (!snap.metadata.fromCache) { const user = snap.data(); // Code here } })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With