For the past two days I've been trying to figure out how to get the notification when the iCloud data has changed. I use a NSPersistentCloudKitContainer and am able to see my changes from one device in another. I just added local notifications to my app and I save the notification to an iCloud entity whenever a user sets it.
Since I'm adding this notification in iCloud, a remote notification with iCloud changes will be sent to the users devices with iCloud enabled. What I would like to do is when the device gets this notification, read from the new data and set a local notification on the current device if a notification entity is found.
But I can not seem to figure out how to intercept this change notification. I tried using didReceive and didReceiveRemoteNotification from the AppDelegate, but none of these functions fired when the device received the iCloud changes. In the Xcode console I can see that the device is notified with the data.
How can I intercept the background notification that contains the new data so I can add a local notification on the device?
Here is how I set up my iCloud container:
class CoreDataManager {
static let sharedManager = CoreDataManager()
private init() {}
//setting the persistentContainer
lazy var persistentContainer: NSPersistentContainer = {
//get local or iCloud container if user wants to use iCloud
var useCloudSync = UserDefaults.standard.bool(forKey: "useCloudSync")
let containerToUse: NSPersistentContainer?
if useCloudSync {
containerToUse = NSPersistentCloudKitContainer(name: "App")
} else {
containerToUse = NSPersistentContainer(name: "App")
let description = containerToUse!.persistentStoreDescriptions.first
description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
}
// Enable history tracking and remote notifications
guard let container = containerToUse, let description = container.persistentStoreDescriptions.first else {
fatalError("Hey Listen! ###\(#function): Failed to retrieve a persistent store description.")
}
description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Hey Listen! Unresolved error \(error), \(error.userInfo)")
}
})
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
container.viewContext.transactionAuthor = appTransactionAuthorName
container.viewContext.automaticallyMergesChangesFromParent = true
do {
try container.viewContext.setQueryGenerationFrom(.current)
} catch {
fatalError("Hey Listen! ###\(#function): Failed to pin viewContext to the current generation:\(error)")
}
// This notification never gets called
NotificationCenter.default.addObserver(
self, selector: #selector(type(of: self).storeRemoteChange(_:)),
name: .NSPersistentStoreRemoteChange, object: container)
return container
}()
You can think of this as a user setting a reminder in the Apple reminders app and how that notification pops up on all of my iCloud devices at the time I set it at.