Syncing of Core Data Transaction Logs (iOS)
It is possible to tell when you device has completed syncing transaction logs by performing a metadata query and checking the uploaded and downloaded status of all the files in the iCloud containers /CoreData directory. For the most part these should be *.cdt and *.zip files and should all have uploaded and downloaded values of 1 (or string equivalent). You MUST check these values using results of the metadata query only(cause Apple says so and any other way seems to result in thread deadlocks).
Deleting an App does NOT delete files in the Apps iCloud container!! (iOS)
Even if you delete files from iCloud (by deleting files from your Mac’s Mobile Documents directory) these deletions will not be synced with the device you deleted the App from immediately. In fact is seems they will only be deleted after reinstalling the App and running it.
So when you reinstall the App it will find any files that were in the iCloud container from the previous install – HOWEVER in around 10 seconds things will sync up (which might mean the files get removed!) So do a metadata query and look for any files in the iCloud /CoreData directory – you will still get a list of the files but the download status will be NOTDOWNLOADED.
Now the tricky part:
- IF you deleted all your documents from iCloud by deleting all directories from the /CoreData subdirectory (using a Mac say), then initially the metadata query will report a downloaded status of NOTDOWNLOADED, but after few seconds (~15) the metadata query will return an empty results set – i.e. no files found in iCloud!! Which is what you expect once iCloud sync’s the deletion with the device. You must run the App for this to happen. So now we load seed data because not iCloud files exist so we assume we are the first device create the store.
- IF you did not delete all your documents from iCloud then when you restart the App you will to get a downloaded status of CURRENT and the App will launch as per usual. We don’t load seed data because iCloud files exist already.
- If you did delete all your documents from iCloud but then started the App on another device using iCloud then iCloud files will exist but they will not be the same files that still exist on the original device. So when you reinstall the App and start it on the original device the device will first remove the old files and then report a downloaded status of NOTDOWNLOADED much like case 1) above except it never clears. So we just sit in a wait loop and after 15 seconds we assume these must be ‘real’ iCloud files. So now we don’t load seed data because iCloud files exist already.
Core Data Sync Status Indicator (iOS)
Ever sat wondering:
- Whether your most recent transactions have been uploaded to iCloud ?
- Whether your App has download all transactions from iCloud ?
Well as long as the devices have access to the network the following approach can be used to tell the status of iCloud syncing. When in Airplane mode the network activity indicator is disabled so the app won’t show any indication using this. Might have to find another way to show that sync is needed when in offline mode!
- Perform a metadata query on the iCloud ubiquity containers /CoreData directory
- Check the results for any files that have not been downloaded (whose attribute value for the NSMetadataUbiquitousItemDownloadingStatusKey is NSURLUbiquitousItemDownloadingStatusNotDownloaded)
- Check the results for any files that have not been uploaded (attribute value for NSMetadataUbiquitousItemIsUploadedKey)
- If all files have been uploaded and downloaded (all files MUST have both) then everything is in sync.
To show that sync is required we also do the following:
- We observe all managedObjectContext saves and set the network activity indicator ON if an iCloud store is being used – we know that as a result of this Core Data will write a transaction log file and we clear the network indicator once all log files are synced (see above).
- We observe the storesDidImport notifications from Core Data and set the network activity indicator ON as well as setting a timer. It may take some time from the time the logs are downloaded to the time that we see the storesDidImport notification. Sometimes the download is so quick we don’t see it at all.
- When the timer is processed we set the network indicator OFF.
And that’s it. Not too hard. Good luck figuring out the code – async and threads makes it tough to follow and debug!