Refresh Firebase iOS SDK cache immediately - ios

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.

Related

Why we need to use NSPersistentHistoryTransaction if NSFetchedResultController able to update UI correctly?

I still fail to understand, what is the problem NSPersistentHistoryTransaction is trying to solve, in the CoreDataCloudKitDemo WWDC 2019 "Using Core Data with CloudKit"
https://github.com/software123inc/CoreDataCloudKitDemo/blob/master/CoreDataCloudKitDemo/DataProvider/CoreDataStack.swift#L161
I want to see, what problem will occur, if processPersistentHistory is not executed.
By making the processPersistentHistory empty, I try to do the following testing.
Run 2 simulators simultaneously in the same machine.
Add an item to simulator A.
Since, there is no way for simulator B to receive push notification, I press the home button for simulator B.
In simulator B, I tap on the app icon to launch the app again.
In simulator B, I can observe controllerDidChangeContent is being called. My guess is that, because the backed SQLite is seamlessly updated by CloudKit background task, NSFetchedResultController will be notified the SQLite DB change, and subsequently update the UI. Check the "Download CloudKit Changes into Core Data" of https://developer.apple.com/documentation/coredata/mirroring_a_core_data_store_with_cloudkit/syncing_a_core_data_store_with_cloudkit
In simulator B, due to controllerDidChangeContent is being triggered correctly, I can observe the UI change perform by NSFetchResultController without issue.
Hence, I am not clear, on what problem processPersistentHistory is trying to solve in the demo code. May I know what kind of test case I can perform, to understand the problem solved by processPersistentHistory?
Based on "Integrate Store Changes Relevant to the Current View"
https://developer.apple.com/documentation/coredata/mirroring_a_core_data_store_with_cloudkit/syncing_a_core_data_store_with_cloudkit
Your app receives remote change notifications when the local store
updates from CloudKit. However, it’s unnecessary to update your UI in
response to every notification, because some changes may not be
relevant to the current view.
Analyze the persistent history to determine whether the changes are
relevant to the current view before consuming them in the user
interface. Inspect the details of each transaction, such as the entity
name, its updated properties, and the type of change, to decide
whether to act.
For more information about persistent history tracking, see Consuming
Relevant Store Changes.
This part is getting confusing. Our NSFetchedResultController is receiving relevant entity change event due to SQLite, and subsequently able to update the UI correct. If that is so, why do we still need persistent history?
You are right that NSFetchedResultsController are able to receive updates, and trigger updates to the UI.
So the question becomes, in which UI of your app that you display data from CoreData, and do not use NSFetchedResultsController?
For mine, it is a form editing an item, which I just pass one of item from the NSFetchedResultsController into it as a form member variable. This Form is not able to receive such updates.
Looking at the CoreDataCloudKitDemo, there's also this DetailView, that is letting user edit a single post, and whenever this post is deleted from another device, having persistent history tracking (and query generation) allow it to "trap" this change and show a pop up before closing the edit form.

How to wait until cloud kit data is being synced with core data in swift in iOS13

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.

Synchronize data between server and iOS application

How to synchronize new data added in the database of server or middle ware to the devices installed our app?
Typically what's done is the app makes a call to the server to refresh the data when it's opened or a refresh has been requested.
If you want the user to know they're missing out on new data, you should use push notifications to let them know the number of new updates.
if you are supporting iOS7 and above you can do background data sync , for more info refer to similar question at Background sync in iOS7

Manage iPhone app both offline and online

I am stuck to a point, I am managing my app offline also.. first time i get all data (images) from a webservices and store its path into sqlite, now I take an int value 0 or 1 and store its state into NSUserDefaults now I am facing problem in updating those images, like if images are changed how should I notify into my app, I searched it on Google and only solution is to send push notification to app when record is updated. What if user do not allow push notification?
Is there any other solution to manage app offline and update only when record is changed from online database?
You can sync your Data with server Periodically , like call a webservice which check if images have been changed then fetch the new images and if images are not changed then continue with old data.You can add a Boolean Value on server end which can tell you if data on server is updated or not or you can check this with Time stamp like when data is updated last time then compare your local time with Server time at which data has been updated . Good Luck !!
There are ways to handle such kind of situation:
Use push notifications which is the best solution for such situation.
Query the server periodically by giving the ability to the user to set the time interval from app settings.
Query the server whenever the app came from background to foreground.
An idea is to use BackgroundFetch to update the app content while it is not running. I am using similar fetch for one of my apps where I update the content before the user opens the app. I am fetching a small list of items that is indicating which one is up to date and which is not. Then, at runtime I present an option to the user to manually update these items, but of course you can also download all that while in backgroundfetch. My app is without network reach most of the time, and backgroundFetch will update the items list first thing when there is some internet connection.
There are two important methods here that you need to register, setMinimumBackgroundFetchInterval: and application:performFetchWithCompletionHandler: . You can read more about them in Apples guides for background modes.
You can also check out this good tutorial about this fetching capability: http://www.appcoda.com/ios7-background-fetch-programming/
There is way which has being most popular as most of peoples are preferring
At server side build mechanism, which can send lists of images updated after particular date/time.
To keep track of last sync date/time at locally.
Pinged on server with last date/time in case of first time pass any past date and check for update, if there is then download updated images, Otherwise.
Now you have to decide this process when would be query to server
1) At every first time application will be load. (At didFinishLaunchingWithOptions).
2) Query the server periodically by giving the ability to the user to set the time interval from app settings or else where would be preferable.
3) Query the server whenever the app came from background to foreground.

icloud core data sync

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.

Resources