I've implemented Firebase Realtime Database in my android app with data persistency. My expectation was that, as data persistence was active, each time my app was open, Firebase would not check for database updates.
Anyway, according to my tests, I noticed that, everytime I open my app, some tests and, according to what I noticed, data usage increased near 10KB. But considering that my app has a service which must check a data in each second, I cannot make device consume internet to check data 3600 times every hour: I'll have to save this specific data locally.
So, that's my question: when data persistence is active in realtime database, why everytime my app is open, data usage is increased in something like 10KB?
Related
I developed core data based app and implemented iCloud sync feature after it was introduced in iOS 13.
I enabled iCloud kit, used NSPersistentCloudKitContainer instead of NSPersistentContainer and added several lines of code to sync core data with iCloud.
Sync works fine. The problem is that when I uninstall app and reinstall app, it doesn't fetch iCloud data at first time.
I have to restart app or open another screens to let Core Data to be synced with iCloud.
Is there anyway I can check if core data is being synced with iCloud or wait until it finishes syncing?
Thanks.
There is no API exposed to get the completion handler on sync of all
CKRecord's to NSManagedObject's.
Also the update is working using a background silent notification so we can expect any change anytime. So its good to not having completion handler
What's next
You can create one attribute to check the sync time, just like a date when last sync happened to local record and check the lastModificationDate (By default CKRecord has this property) of the same record in iCloud.
So everytime when you launch the app check for all the records manually if any update is required, then wait for notification of update and keep on checking the sync status
Note: Be careful this may lead to delay your launch process if from any other device user is very active and new records are getting inserted or modified.
Currently, there is no API provided for iCloud sync completion. What you can do is
You can initialize NSPersistentCloudKitContainer and call it's loadPersistentStores() at the start of the app. This will buy you enough time and your data will be available for your internal screens.
You can also listen for remote changes in your local store and update your UI accordingly as mentioned in this Apple doc: https://developer.apple.com/documentation/coredata/consuming_relevant_store_changes
I have to restart app or open another screens to let Core Data to be
synced with iCloud.
To solve this I'm using a notification observer for NSManagedObjectContextObjectsDidChange event.
When reinstalled app is first opened, it shows empty screen and after some time, when data is synced, the notification is triggered and the page is reloaded with the data.
However I also couldn't find any way to wait and show loading message while data is being synced.
My app has Background App Refresh when it receives a Push Notification where it fetches data from the server and stores using Core Data, now I need to process the data when the App is becomes active again. So, I tried the fetch query when -(void)applicationDidBecomeActive:(UIApplication *)application is called to get the data.
But, if I directly query the tables immediately, the query returns 0 objects if the App is in stopped state. I guess the Core Data connectors are not prepared by the time I call the query. I am sure that the data is saved in the tables as if I make the query using dispatch_after 2 secs , I get the complete data.
I do not want to make the Query on viewDidLoad/viewDidAppear cause, it is not necessary that these will be called when the app goes becomes active from non active state.
Is there a way to manually and immediately refresh the Firebase cache, using the iOS SDK, to pull down the latest data (assuming you are online)? For example, if I made some changes to my data on Firebase, I want my app to reflect that immediately, but with persistence turned on, it usually takes a few restarts of the app.
I recently turned on persistence in my app like so:
Firebase.defaultConfig().persistenceEnabled = true
It worked great, but now my app doesn't refresh it's data very often even with an internet connection. I'm using the offline capabilities mentioned here.
I had the same problem with persistence and here are two options solving it:
1) Keep using observeSingleEventOfType but setting ref.keepSynced(true). This won't listen to changes happening in your data but it refreshes data once this code is executed. I've chosen this option for my FAQ section which just needs to update once when the screen is opened (viewDidLoad).
2) Use observeEventOfType. This will always keep your data in sync and will execute again as soon as your data changes.
When using Firebase in an iOS app I would want to give the users the option to sync their data into the Firebase cloud or just keep everything local. I've seen that Firebase has introduced the option in their SDK to go offline and keep the data from syncing online but I'm not sure about the intent of the feature.
//Keep data local.
[Firebase defaultConfig].persistenceEnabled = YES;
self.firebase = [[Firebase alloc] initWithUrl:kFirechatNS];
[Firebase goOffline];
From the documentation it seems that the goOffline(), and offline mode in general, is build to handle temporary periods where the device is offline, and sync data back in to the cloud as soon as the device becomes online again. Would the Firebase offline mode be capable of handling a "permanent offline" scenario? Or would forcing Firebase to go "permanently offline" lead firebase to just accumulate more and more "meta data" for a never occurring future sync to the cloud? Or discard old data at some point? Or run out of offline cache disk space when a max cache size is reached ?
I got answer from Firebase support:
While you can use goOffline() to force the client offline for a long time, performance will deteriorate over time. The Firebase clients will queue intermediate state changes, instead of updating the stored state as the server does.
I am starting out with building a iOS app which will utilize core data and will sync its data with other devices through iCloud. I was thinking of giving a "Sync" button so that the data is not modified at random moments by data from iCloud. The following situation would then occur :-
User A is working on device A and adds two records. User B is currently working on device B and does not press the Sync Button. At night, the user B decides to update the data in device B and presses the Sync Button (I have the following questions regarding this situation) :-
Can the method mergeChangesFromContextDidSaveNotification insert those two records after the Sync button is pressed ? (I think it can. However, just want to confirm before proceeding ahead with this model)
Is it possible to access the properties of those two objects before inserting them into the database of device B ?
I do not think that iCloud is designed for your use case. iCloud syncs data across devices for the same user i.e. one that is logged in with the same Apple ID in more than one device. The idea is that when the user opens the app on a different device, he can continue working with the data he created / modified on another device before.
There is quite a bit of latency in the updates, so even if you enable / disable syncing via a "Sync" button the actual delivery time is not guaranteed and can take pretty long in some cases depending on connection speeds, chance, the state of Apple servers, etc.
Instead, you could devise a customised solution based on your own server and data scheme.
Since you're using iCloud with Core Data-- no, you can't do anything like this. When iCloud syncs Core Data changes, it does so in the background. It downloads the changes, saves them to the data store, and then, after it's done it tells you about the change that has already happened. Calling mergeChangesFromContextDidSaveNotification does not save the changes-- they're already saved. What that call does is update your managed object context with new data from the persistent store. You get notified of new insertions after they have already happened. Think of the "did import" notification as if it were a "did save" notification from another thread, telling you about something that's already finished.
Now, if you have already loaded a managed object when you receive the import notification, you could compare its current properties to those from the most recent incoming change update. If you don't already have the object in memory, you can't get its old values, because they've already been overwritten.