You DO need to enable persistent history tracking so that the device is able to catch up if a user enables/disables/re-enables your Apps use of iCloud by turning off your Apps access to iCloud Drive or via some feature you've implemented.
NSPersistentCloudKitContainer
uses the history and handles it for you behind the scenes. You do NOT need to do anything with history, although you can if you want. The Apple Docs are a little fuzzy on that point.
What I did (and deployed) was to give users a switch in the App to allow them to enable/disable the Apps use of iCloud. It is specific to the App on that device and the setting is NOT persisted via ubiquitous defaults to any other device. I prefer not to encourage them to disable their main source of backup. All it does to disable is set the Container Identifier to nil and when enabled to the container ID string as shown below. This was stated as OK to do by an Apple CloudKit engineer in the Apple Developer Forums. When a user flips this I instruct them to fully restart the App. So far it seems harmless and in all my testing it works fine.
Set your CoreData stack like this:
@objc func initCoreDataStack()
{
guard let description = pc.persistentStoreDescriptions.first else {
fatalError("*** CoreDataUtil - could not find persistent store description.")
}
description.setOption(true as NSNumber, forKey:NSPersistentHistoryTrackingKey)
description.setOption(true as NSNumber, forKey:NSPersistentStoreRemoteChangeNotificationPostOptionKey)
//
// If user wants iCloud Storage set id, else set it to nil
// but with history on (see above) so that if they enable it
// later there is a history of changes.
//
if(useiCloud == true) {
let cloudKitContainerIdentifier = "iCloud.your.container"
let options = NSPersistentCloudKitContainerOptions(containerIdentifier:cloudKitContainerIdentifier)
description.cloudKitContainerOptions = options
}
else {
description.cloudKitContainerOptions = nil
}
pc.persistentStoreDescriptions.first?.url = storeURL()
pc.viewContext.automaticallyMergesChangesFromParent = true
pc.loadPersistentStores { _, error in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
// Set this here so that updates by consumers are dynamic
self.pc.viewContext.automaticallyMergesChangesFromParent = true
// My code does this for consumers of this singleton.
self.sendMOCReadyNotificationForPlatform()
}
}
NSPersistentHistoryTracking
is automatically implemented for eachNSPersistentCloudKitContainer
. What you might need to be aware of is that if your store (for example the sqlite file) existed before you implementedNSPersistentCloudKitContainer
(i.e. its was simplyNSPersistentContainer
) then history tracking would not have been automatically implemented and therefore only newly inserted objects will register with CloudKit. – CracklingNSPersistentHistoryTrackingKey: 1
so it appears to be enabled by default. – Villatoro