【问题标题】:Core Data and CloudKit sync is inconsistentCore Data 和 CloudKit 同步不一致
【发布时间】:2021-07-19 23:44:01
【问题描述】:

我有一个使用公共数据库的应用程序,它使用 Core Data 和 CloudKit。问题是删除似乎永远不会同步,添加和更改直到应用程序进入后台然后返回前台才会显示,甚至这些结果也不一致。

示例应用只是您在指定 SwiftUI 和 Core Data 时获得的默认应用。我在 CloudKit 仪表板中修改了 Schema,添加了两个索引 recordName 和 modifiedAt。

下面是 Persistence.swift 文件,所以要复现,新建一个项目,选择 Core Data 和 Use CloudKit,Add Capability for CloudKit 和 Remote Notifications,然后将 Persistence.swift 内容替换为上面的内容。

import CoreData

struct PersistenceController {
    static let shared = PersistenceController()

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        for _ in 0..<10 {
            let newItem = Item(context: viewContext)
            newItem.timestamp = Date()
        }
        do {
            try viewContext.save()
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
        return result
    }()

    let container: NSPersistentCloudKitContainer

    init(inMemory: Bool = false) {
        container = NSPersistentCloudKitContainer(name: "TestCKSink")
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        
        guard let description = container.persistentStoreDescriptions.first else
        {
            fatalError()
        }
        //description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        description.cloudKitContainerOptions?.databaseScope = .public
        container.viewContext.transactionAuthor = "Me"
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {

                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    }
}

我已经尝试过启用和不启用历史跟踪选项。正如我所说,这在某些时候有效。我也意识到我需要添加代码来强制刷新显示,但即​​使检查 CloudKit 仪表板并查询记录,有些根本没有显示在那里或需要很长时间才能到达(18 分钟)。

欢迎提出任何建议。

【问题讨论】:

  • 这里有一个WWDC video,看起来您缺少基本设置中的一些代码,例如setQueryGenerationForm,您应该查看整个视频,但代码似乎在第 2 分钟左右: 57
  • 感谢您的回复。这并没有帮助,当 Nick Gillette 审查代码时,他将代码排除在同步工作所需的内容之外。不太清楚它的作用。
  • 我并没有完全解决这个问题,但我怀疑我所看到的是公共数据库中的一些损坏,导致同步无法 100% 工作。当我从公共选项切换到私人选项时,事情开始起作用了。我怀疑这是因为我又从头开始了,不知道使用公共数据库是否有什么意义。我最终会尝试清除公共数据库并切换回它,届时将发布结果。在我这样做之前可能需要一段时间。
  • 我相信 2020 年的 WWDC 视频中提到只有私有数据库会收到推送通知。这个想法是公共数据库用于模板和稀有共享对象。因此,您必须显式轮询以获取更新。切换到私有数据库使其工作。我不喜欢这如何限制由公共 CloudKit 数据库支持的核心数据的用例。当您直接访问 Cloudkit 数据库时,支持更改推送通知。我过去曾让这些订阅工作。如果可以选择获得该功能,我会很高兴!
  • 我没有使用“at”FetchRequest,而是使用例程直接读取数据库。一旦我将其更改为“at”FetchRequest,它就可以正常工作,但我也发现模拟器很少正常工作,但实际设备可以正常工作,但有一些例外。

标签: swift core-data cloudkit


【解决方案1】:

我前段时间遇到过类似问题,在初始化托管对象上下文时尝试以下设置:

managedObjectContext.automaticallyMergesChangesFromParent = true

【讨论】:

  • 我已经在那里了。我怀疑我的问题可能来自我正在同步的内容的大小。一些文本字段可能非常大。
猜你喜欢
  • 2022-07-03
  • 2017-08-06
  • 1970-01-01
  • 2020-11-02
  • 2020-03-26
  • 2020-02-16
  • 2014-08-31
  • 2016-01-27
  • 2017-04-13
相关资源
最近更新 更多