Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronising old data with NSPersistentCloudKitContainer

I'm using NSPersistentCloudKitContainer to synchronise data between different devices with CloudKit. It works perfectly well with a new project, however when I'm using it with old projects the old data which was added with NSPersistentContainer does not synchronise.

What I would like to achieve is to synchronise old data that was added with NSPersistentContainer after changing it to NSPersistentCloudKitContainer. Is it possible?

like image 258
Wojtek Avatar asked Jul 03 '19 18:07

Wojtek


1 Answers

I've found a solution that works for my Core Data database - and mine is quite complex with multiple many-to-many relationships (A surgery/anaesthesia logbook app called Somnus)

I started by creating a new attribute for all my Core Data Entities called sentToCloud and setting it to FALSE by default in the Core Data model.

On the first load for an existing user:

  • Fetch request using the predicate "sentToCloud == FALSE" for each Entity type
  • Change sentToCloud to TRUE for each Object then save the MOC
  • This triggers NSPersistentCloudKitContainer to start syncing

I've done this in order of 'priority' that works for my database, assuming the iCloud sync sessions match the order in which Core Data is modified. In my testing this seems to be the case:

  • I first sync all child (or most child-like) Entities
  • Then sync their parents, and so on, up the tree
  • I sync the Object the user interacts with last, once everything else is in place so the relationships are intact and they don't think their data is borked while we wait for NSPersistentCloudKitContainer to reconnect all the relationships
  • I also leave any binary data (magically turned into a CKAsset behind-the-scenes) to last as it's not the most important part of my database

My database synced successfully from my iPad to iPhone and all relationships and binary data appear correct.

Now all I need is a way to tell the user when data is syncing (and/or some sort of progress) and for them to turn it off entirely.

ADDENDUM

So I tried this again, after resetting all data on the iCloud dashboard and deleting the apps on my iPhone & iPad.

Second time around it only synced some of the data. It seems like it still has a problem dealing with large sync requests (lots of .limitExceeded CKErrors in the console).

What's frustrating is that it's not clear if it's breaking up the requests to try again or not - I don't think it is. I've left it overnight and still no further syncing, only more .limitExceeded CKErrors.

Maybe this is why they don't want to sync existing data?

Personally, I think this is silly. Sometimes users will do a batch process on their data which would involve updating many thousands of Core Data objects in one action. If this is just going to get stuck with .limitExceeded CKErrors, NSPersistentCloudKitContainer isn't going to be a very good sync solution.

They need a better way of dealing with these errors (breaking up the requests into smaller requests), plus the ability to see what's going on (and perhaps present some UI to the user).

I really need this to work because as it stands, there is no way to synchronise many-to-many Core Data relationships using CloudKit.

I just hope that they're still working on this Class and improving it.

like image 162
Paul Martin Avatar answered Oct 21 '22 16:10

Paul Martin