将核心数据同步到 CloudKit Public 数据库

Synchronizing Core Data to CloudKit Public Database

在下面的 link 中,有一个项目的源代码,它允许您在相同的用户设备之间同步核心数据。数据存储在用户私有数据库中...有没有办法从 public CloudKit 数据库中的 CoreData 同步数据,以便所有应用程序用户之间的应用程序都相同? 为什么 NSPersistentCloudKitContainer 不允许你设置这个?

https://developer.apple.com/documentation/coredata/synchronizing_a_local_store_to_the_cloud

现在可以在 iOS 14.0+ Beta 和 macOS 11.0+ Beta 中通过新的 databaseScope 属性: https://developer.apple.com/documentation/coredata/nspersistentcloudkitcontaineroptions/3580372-databasescope

可能的值为 .public(public 数据库)、.private(私有数据库)和 .shared(共享数据库)。

例如:

let container = NSPersistentCloudKitContainer(name: "test")
guard let description = container.persistentStoreDescriptions.first else {
    fatalError("Error")
}
description.cloudKitContainerOptions?.databaseScope = .public

视频 https://developer.apple.com/videos/play/wwdc2020/10650 介绍了如何通过将 databaseScope 值设置为 .public.

来将核心数据存储与 CloudKit public 数据库同步

您可能还需要 #available 检查以确保向后兼容性,即:

if #available(iOS 14.0, *) {
    description.cloudKitContainerOptions?.databaseScope = .public
} else {
    // Fallback on earlier versions
}

要回答评论中的最后一个问题,是的,可以使用 .public 和 .私人在同一家商店。这是项目的link:Messanger by Patrick Maltagliati on 10/2/20

   init(inMemory: Bool = false) {
    container = NSPersistentCloudKitContainer(name: "Messanger")
    
    let defaultDesctiption = container.persistentStoreDescriptions.first
    let url = defaultDesctiption?.url?.deletingLastPathComponent()
    
    let privateDescription = NSPersistentStoreDescription(url: url!.appendingPathComponent("private.sqlite"))
    let privateOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.com.Maltagliati.Messanger")
    privateOptions.databaseScope = .private
    privateDescription.cloudKitContainerOptions = privateOptions
    privateDescription.configuration = "Private"
    privateDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    privateDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
    
    let publicDescription = NSPersistentStoreDescription(url: url!.appendingPathComponent("public.sqlite"))
    let publicOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.com.Maltagliati.Messanger")
    publicOptions.databaseScope = .public
    publicDescription.cloudKitContainerOptions = publicOptions
    publicDescription.configuration = "Public"
    publicDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    publicDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
    
    container.persistentStoreDescriptions = [privateDescription, publicDescription]
    
    if inMemory {
        container.persistentStoreDescriptions.forEach { [=10=].url = URL(fileURLWithPath: "/dev/null") }
    }
    
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
}