Hi,
It's a great Sync method!! First of All really thanks for it! ;) And I will use for my new IOSApp, and I also wanna create a tutorial for it. I have only one annoying thing with your codes, the duplications after synchronization.
I have a CoreData stack, and I'm importing for 2 entity 10 and 15 objects at the First launch. Sync is running every time when you open or close the app, but not at First launch (cause problems with import, because it is so slow, that the UI update and other codes can't wait the end of the Sync). And of course, at the very first launch, the user hasn't got any objects, so don't need to sync the database.
But if you imported these objects, and after that delete the App, and later download it again (I'm just test it now from Xcode on real device, and delete the app form device and start running again), the App has a First Launch, so the import starts, but you check just the ObjectID in the CoreDataChangeManager, and not the Object properties. I believe this is a mistake, because, if I create a new Object, the Object ID will be different, even if the object property is the same. So for 1 entity, there will be not 15 object, there will be 30. And later when the sync starts, in the App these objects will duplicate.
I wrote a code for this situation, to delete those object, if they have for example the same name property, or the same displayOrder property. But this is not a perfect solution (I checked the objects at a collection view, but the import is running at launch, sot till i go to that collection view, these objects still duplicated, which can cause other problems too).
So I suggest a solution, if you could set for CoreDataChangeManager a "mainattribute", wich could set globally in AppDelegate, or anywhere else, as the Synchronizer, than developers could set 1 attribute to every Entity, as a main attribute, which can't be the same, so you should write an if statement for the "mainattribute", in this block: - (QSSyncedEntity *)createSyncedEntityForRecord:(CKRecord *)record
, to check if it already exists, and if yes, than avoid the targetContext insertation.
The second solution this "after deletion" what I'm using now, if after the Sync, there are duplications, than I delete the objects with the same name or other property. And for those who have Problems with these things it is strongly recommended to running Sync after every deletion in the App! so with this logic:
[self.managedObjectContext deleteObject:deleteTarget];
[self.managedObjectContext save:nil];
NSLog(@"deleted!");
[self startSync];
And yes there are some words about this SycKit hasn't got Deduplicator, and developer has to write one, but deduplicator for the CoreCata object in the app locally is different as a deduplicator for the CloudKit what you made, so you should improve it. And of course easier modifying your codes and using a global variable implement in a unique App, as with a unique property/database overwrite your SyncKit changemanager, which is otherwise awesome! ;)