CoreData 和 CloudKit Sync 可以工作,但 NSPersistentStoreRemoteChange 通知永远不会触发

Son*_*ach 6 notifications core-data push-notification swift cloudkit

我已经更新了现有的 CoreData 应用程序以使用 CloudKit,以便它可以在多个设备之间保持数据同步(对于同一 iCloud 帐户)。

有用!数据同步就好了。

但主 UIViewController 的视图不反映新数据。要查看更改,我必须切换到不同的视图,然后切换回refreshData()在其viewWillAppear()函数中有调用的主视图。然后,它从数据存储中重新读取并显示所有数据(包括在其他设备上更新的数据)。

UIViewController 应该NSPersistentStoreRemoteChange按照viewDidLoad()以下方式观察通知:

    override func viewDidLoad() {
        super.viewDidLoad()
    //  NotificationCenter.default.addObserver(self, selector: #selector(handleRemoteChange), name: .NSPersistentStoreRemoteChange, object: AppDelegate.appDelegate().persistentContainer.persistentStoreCoordinator)
        NotificationCenter.default.addObserver(self, selector: #selector(handleRemoteChange), name: .NSPersistentStoreRemoteChange, object: nil)
    }
Run Code Online (Sandbox Code Playgroud)

但处理函数永远不会被调用:

    @objc func handleRemoteChange(notification: Notification) {
        print("Handling remote change to data in Collection Controller")
        refreshData()
    }
Run Code Online (Sandbox Code Playgroud)

该打印语句永远不会打印任何内容,并且在那里设置的断点也永远不会触发。

NSPersistentCloutKitContainer我已将托管对象上下文配置为在创建后立即根据需要合并来自父级的更改:

    container.viewContext.automaticallyMergesChangesFromParent = true
Run Code Online (Sandbox Code Playgroud)

该应用程序具有我在网络(和 Stack Overflow)中搜索线索后了解到的所有相关 iCloud 功能和权利,包括:

  • “远程通知”(后台模式)
  • “CloudKit”(iCloud)
  • 已创建并选择一个容器,其标识符格式如下:iCloud.reverse.domain.app

容器的 persistenceStoreDescription 的NSPersistentStoreRemoteChangeNotificationPostOptionKey选项设置为 true:

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                print("FAILED to load persistent store:\(storeDescription)\nERROR:\n\(error)\n\(error.userInfo)")
            }
        })

        container.viewContext.automaticallyMergesChangesFromParent = true
        for description in container.persistentStoreDescriptions {
            description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        }
Run Code Online (Sandbox Code Playgroud)

显然数据同步正常。这只是通知没有按预期工作。因此最终用户不会自动看到新的/同步的数据。

我怎样才能让它发挥作用?

小智 9

我有同样的问题,并通过在调用 loadPersistentStores(completionHandler:) 之前配置自定义持久存储描述来解决

container = NSPersistentCloudKitContainer(name: "RubikClub")
// turn on persistent history tracking
let description = container.persistentStoreDescriptions.first
description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description?.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
NotificationCenter.default.addObserver(self, selector: #selector(type(of: self).storeRemoteChange(_:)), name: .NSPersistentStoreRemoteChange, object: container.persistentStoreCoordinator)

container.loadPersistentStores { (_, error) in
  if let error = error {
    fatalError("init core data error: \(error.localizedDescription)")
  }
}
container.viewContext.automaticallyMergesChangesFromParent = true
Run Code Online (Sandbox Code Playgroud)

  • 18个月后,终于解决了!这里的关键是我需要在调用“loadPersistentStores”之前设置“NSPersistentStoreRemoteChangeNotificationPostOptionKey”。我是用相反的方式做的。我现在更新了问题,以明确我做错了什么,并展示如何不这样做。哎哟!谢谢。 (3认同)