1

我有一个 Core Data+CloudKit 配置,我需要为用户提供一些初始数据作为起点。它只有几个记录/对象,所以起初我尝试硬编码数据并在首次启动时写入核心数据。然后,用户可以添加和更改起点数据。

当我启用 CloudKit 同步时,我发现当启动同一帐户的第二台设备时,从 CloudKit 的角度来看,该设备新写入的默认数据是“更新的”。这意味着第二台设备上的默认数据将同步并覆盖用户自己在第一台设备上的数据。那很糟。

我相信正确的解决方案是在应用程序中提供预填充的核心数据文件 (.sqlite) 文件,以便在首次启动时,默认数据已经比用户在其他设备上创建的任何内容都旧。大多数教程和示例代码都非常古老,引用了 Swift 3、Xcode 7 等。我正在寻找一个在使用 NSPersistentCloudKitContainer 时有效的解决方案。

我在这个 SO question的答案中尝试了代码,将persistentContainer 的类型更改为 NSPersistentCloudKitContainer。这会编译并运行,但结果是我的应用程序在没有预加载数据的情况下启动,我不知道为什么。我在我的 Xcode 项目中包含了三个 .sqlite 文件,并将它们添加到“构建阶段”中的“复制捆绑资源”列表中。

这是我的代码:

lazy var persistentContainer: NSPersistentCloudKitContainer = {

    let appName = Bundle.main.infoDictionary!["CFBundleName"] as! String
    let container = NSPersistentCloudKitContainer(name: appName)
    
    //Pre-load the default Core Data (Category names) on first launch
    var persistentStoreDescriptions: NSPersistentStoreDescription

    let storeUrl = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first!.appendingPathComponent(appName + ".sqlite")
    let storeUrlFolder = FileManager.default.urls(for: .documentDirectory, in:.userDomainMask).first!

    if !FileManager.default.fileExists(atPath: (storeUrl.path)) {
        let seededDataUrl = Bundle.main.url(forResource: appName, withExtension: "sqlite")
        let seededDataUrl2 = Bundle.main.url(forResource: appName, withExtension: "sqlite-shm")
        let seededDataUrl3 = Bundle.main.url(forResource: appName, withExtension: "sqlite-wal")

        try! FileManager.default.copyItem(at: seededDataUrl!, to: storeUrl)
        try! FileManager.default.copyItem(at: seededDataUrl2!, to: storeUrlFolder.appendingPathComponent(appName + ".sqlite-shm"))
        try! FileManager.default.copyItem(at: seededDataUrl3!, to: storeUrlFolder.appendingPathComponent(appName + ".sqlite-wal"))
    }
    
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
         
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()
4

1 回答 1

1

我相信您没有看到任何数据,因为您的代码会查看.documentDirectory, PersistentCloudKitContainer 默认会在 Application Support 目录中查找数据库。

于 2020-07-03T08:36:24.073 回答