核心数据和CloudKit同步WWWDC 2019不适用于Beta 3

时间:2019-07-06 12:14:42

标签: core-data synchronization cloudkit

我正在尝试复制WWDC关于自动将核心数据与云工具包同步的演讲的结果。

我尝试了三种方法:

  1. 制作一个新的主从视图应用程序,并按照中的步骤进行操作 wwdc 2019演讲,在这种情况下,没有同步发生

  2. 在这种情况下,也不会下载任何示例wwdc 2019应用程序

  3. 我制作了一个带有少量核心数据和云工具包容器的小型应用程序,在这种情况下,发生了同步,但我必须重新启动该应用程序。我怀疑这与历史记录管理有关,因此观察到NSPersistentStoreRemoteChange通知并非一无所获。

感谢任何帮助。

5 个答案:

答案 0 :(得分:3)

还遇到了未发送.NSPersistentStoreRemoteChange通知的问题。

Apples示例中的代码

// Observe Core Data remote change notifications.
        NotificationCenter.default.addObserver(
            self, selector: #selector(type(of: self).storeRemoteChange(_:)),
            name: .NSPersistentStoreRemoteChange, object: container)

对我来说,解决方案不是将容器设置为通知的对象,而是设置为nil。还是不使用它并阻止接收通知:

// Observe Core Data remote change notifications.
        NotificationCenter.default.addObserver(
            self, selector: #selector(type(of: self).storeRemoteChange(_:)),
            name: .NSPersistentStoreRemoteChange, object: nil)

答案 1 :(得分:2)

我遇到了同样的问题,原因是必须在您的设备中启用iCloudDrive。在每台设备的“设置”中进行检查

答案 2 :(得分:1)

我还玩过CoreData和iCloud,它运行完美。我想列出一些可以帮助您进一步发展的重要观点:

  • 您必须使用iCloud Acc在真实设备上运行该应用
  • 确保已为您的应用添加了Push NotificationiCloud功能。确保您没有iCloud容器的Dave问题(在这种情况下,您将在Xcode的iCloud会话上看到红色文本)
  • 为了自动刷新视图,您需要将此行添加到Core Data Stack中:container.viewContext.automaticallyMergesChangesFromParent = true

代码:

public lazy var persistentContainer: NSPersistentCloudKitContainer = {
        /*
         The persistent container for the application. This implementation
         creates and returns a container, having loaded the store for the
         application to it. This property is optional since there are legitimate
         error conditions that could cause the creation of the store to fail.
         */
        let container = NSPersistentCloudKitContainer(name: self.modelName)
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                /*
                 Typical reasons for an error here include:
                 * The parent directory does not exist, cannot be created, or disallows writing.
                 * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                 * The device is out of space.
                 * The store could not be migrated to the current model version.
                 Check the error message to determine what the actual problem was.
                 */
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()
  • 添加一些数据时,通常您应该看到控制台日志以CloudKit: CoreData+CloudKit: ..........开头
  • 有时数据不会立即同步,在这种情况下,我强行关闭应用程序并构建一个新应用程序,然后数据才能同步。
  • 曾经有一次,数小时后数据同步:(

答案 3 :(得分:1)

我发现NSPersistentStoreRemoteChange通知是由NSPersistentStoreCoordinator发布的,而不是由NSPersistentCloudKitContainer发布的,因此以下代码解决了该问题:

// Observe Core Data remote change notifications.
NotificationCenter.default.addObserver(
        self, selector: #selector(self.storeRemoteChange(_:)),
        name: .NSPersistentStoreRemoteChange, object: container.persistentStoreCoordinator)

答案 4 :(得分:1)

我知道此答案来得很晚,并且所指的WWDC 19 SynchronizingALocalStoreToTheCloud Apple's sample project并不具体,但是我遇到了同步问题(不是在启动时出现的,而是在同步时出现的)很好,但仅在应用程序处于活动状态但处于空闲状态时才出现,这似乎是原始问题的情况3),该项目使用的是Core Data + CloudKit与NSPersistentCloudKitContainer,并且我相信我遇到的同样问题-现在显然已经解决了-将来可能会影响其他用户阅读此问题。

我的应用从一开始就使用Xcode的11个Master-Detail模板以及Core Data + CloudKit构建而成,因此我只需要做很少的工作即可开始进行同步工作:

  1. 在目标的“签名和功能”中启用远程通知后台模式;
  2. 为CloudKit添加iCloud功能;
  3. 选择容器 iCloud.com.domain.AppName
  4. 添加viewContext.automaticallyMergesChangesFromParent = true

基本上,我遵循Getting Started With NSPersistentCloudKitContainer by Andrew Bancroft,这足以使MVP在设备(Catalina,iOS 13,iPadOS 13)之间(不仅在启动时)而且在应用程序正在运行且处于活动状态时保持同步 / strong>(由于上述第4步),另一台设备已编辑/添加/删除了对象。
作为Xcode模板,它没有WWDC 2019样本项目的其他自定义/高级行为,但实际上已完成该目标非常好,我很满意,所以我继续进行此应用程序开发的其他部分,并不再考虑同步。

几天前,我注意到iOS / iPadOS应用程序现在仅在启动时进行同步,而不是在该应用程序在屏幕上处于活动和闲置状态时;在macOS上,此行为略有不同,因为重新激活应用程序时,简单的命令选项卡触发了同步,但是如果Mac应用程序位于最前端,则不会同步来自其他设备的更改。

最初,我指责我在此期间所做的一些修改:

  • 为了在共享扩展中访问sqlite,我通过将NSPersistentCloudKitContainer子类化,将容器移至应用程序组中。
  • 我更改了应用程序名称的大小写,并且由于无法删除CloudKit数据库,因此创建了一个名为 iCloud.com.domain.AppnameApp 的新容器。不区分大小写,显然,是的,我真的应该开始不再在意这类事情了。

虽然我很确定自己在每次更改之后都看到了同步工作,但是同步(显然)突然中断了我至少几个小时的时间,使我确信其中任一修改是默认的路径导致在应用程序处于活动状态时停止接收通知,然后合并将仅在启动时发生(如我所见),因为正在运行的应用程序没有意识到更改。

我应该提到,因为这可以帮助其他人解决我的情况,所以我确定由于CloudKit仪表板显示正在发送的通知,因此在保存Core Data上下文时触发了通知:

CloudKit Dashboard historical push logs

因此,我尝试了几次清除“派生数据”(一个永远不知道),删除所有设备上的应用程序并重置CloudKit仪表板中的开发环境(在开发过程中我已经定期进行的操作),但是我仍然有没有收到通知的问题。

最后,我意识到重置CloudKit环境并删除应用程序确实很有用(实际上,为了安全起见,我重新启动了所有内容 ),但是我还需要删除应用程序数据从iCloud (如果我真的想要一个干净的表盘,则从iCloud的“设置”屏幕上,该iOS设备仍在安装该应用程序的最后一个iOS设备上)。否则,我有些混乱的数据库将同步回新安装的应用程序。

实际上,具有全新开发环境的全新平板电脑,新安装的应用程序和重新启动的设备也恢复了从设备检测到的通知,即使这些应用程序位于最前面
因此,如果您认为自己的设置正确无误,并且已经阅读了足够多的内容,那么viewContext.automaticallyMergesChangesFromParent = true是您唯一需要的东西,但是仍然看不到其他设备发出的更改,请不要排除某些东西可能已经被弄乱了您的控件(不要误会我的意思:我100%肯定它一定是我做的!),然后尝试重新开始...这似乎有些晦涩,但是我们为应用选择的同步方法不是什么