I am having trouble synchronizing my local data with Parse data when using ´enableLocalDataStore´. If I don't use local storage everything is fine, but I would like to minimize calls to Parse server. I understand that if I use ´saveEventually´ for newly created objects these will persist (pinned) locally and be synced with Parse when internet connection is available. This also works fine. My problem is that I don´t know the best method to update the local 'dataStore' with Parse 'dataStore' except to call a method that fetches changes remotely and updates locally. Currently, use the following:
-(void) fetchAllFavorites{
PFQuery *query = [PFQuery queryWithClassName:@"UserStats"];
[query fromLocalDatastore];
[[query findObjectsInBackground] continueWithBlock:^id(BFTask *task) {
if (task.error) {
}
else
{
[PFObject pinAll:task.result];
}
return task.result;
}];
}
This approach does not account for changes that may have occurred in Parse 'dataStore'. I could just unpin all local objects and fetch whatever is in Parse by calling a method directly. However, I would think there would be a better approach that seamlessly syncs local changes with changes in the Parse 'dataStore'? Is that not the idea behind allowing the use of 'localDataStore' in the first place ? Currently, I can only see that this works one way: you store data locally and then update the Parse 'dataStore' manually, but you don't really sync between these. At least this is the idea I get from some of the examples and I wonder if anyone has a good approach to how to: how to enable 'localDataStore' that is continuously synchronized with Parse 'dataStore'? Any suggestions and examples would be very helpful. I am programming in Cocoa but Java examples would also be great. Thanks, T.
My solution to this was to do a local query, and if nothing is there then query the server. In my settings page I have a function that will "sync" with server, fully refresh the pinned objects basically. This isn't that necessary since any time the user edits, removes, or adds an object, I am calling saveEventually
, deleteEventually
, pinInBackground
, unpinInBackground
, as appropriate. My startup function looks like this. If local objects aren't found, the server is queried and they are pinned so that next time it will only be local.
PFQuery *localQuery = [PFQuery queryWithClassName:@"ClassName"];
[localQuery fromLocalDatastore]; // and any other constraints
[localQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if(objects.count > 0) {
self.objects = objects;
} else {
PFQuery *remoteQuery = [PFQuery queryWithClassName:@"ClassName"];
[remoteQuery findObjectsInBackground:^(NSArray *objects, NSError *error) {
if (objects) {
self.objects = objects;
[PFObject pinAllInBackground:objects];
}
}];
}
}];
My approach was to write an utility that checks whether something was updated or deleted in the cloud. Everytime I needed to do an update I called:
[[ParseLocalDataStoreManager sharedInstance]updateClasses:classes];
//classes is a NSArray
I kept track of which classes were already in the localStore and which were not. If a class was not, then I queried and pinned all of its objects. If it was, I only updated the objects that were modified in the cloud, after the last date I updated. I used Parse's
[query whereKey:@"updatedAt" greaterThanOrEqualTo:lastUpdated];
and kept record of lastUpdated
in 'NSUserDefaults'.
To delete the objects that were no longer in the cloud, I wrote a small cloud function that returned the objects on the cloud for a certain class. Then I compared them to what I had in localStore, and deleted those that were not in the Cloud.
In my case I updated everytime the user opened the app, since no real-time updates were needed. But if you need real time updates, you can set a timer, and call the function update with the classes you want to update in real time.
I uploaded the utility to github: https://github.com/timpalade/ParseLocalDataStoreManager
Intstructions as well as the cloud code can be found on github. Hope this helps!
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