首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >核心Data+CloudKit未连接到CloudKit

核心Data+CloudKit未连接到CloudKit
EN

Stack Overflow用户
提问于 2020-07-13 00:19:13
回答 2查看 917关注 0票数 3

我正在更新一个前置I 13核心数据应用程序,以使用Core Data+CloudKit同步来支持多个设备上的单个用户。同步应该是自动发生的,在我开发的一个临时步骤中,它确实起了作用。现在它不起作用了,CloudKit遥测技术没有记录任何活动,我也不知道为什么它不起作用。

在我以前的应用程序版本中,我在UserDefaults中提供了少量的标签字符串,允许用户修改它们,并将更新的版本放回UserDefaults中。这是一种快捷方式,可以避免管理第二个核心数据实体,因为只有少量的对象。

从那时起,我就意识到这在多设备实现中是行不通的,因为本地Core数据数据库是空的这一事实不再意味着它是该用户的第一次使用。相反,每个新设备都需要查找基于云的数据源,以查找用户正在使用的标签字符串,并且只有在用户没有其他东西的情况下才使用应用程序提供的默认值。

我遵循了苹果对用CloudKit建立核心数据的指示,一开始同步工作得很好。但后来我意识到同步行为是不正确的,我真的需要提供一个预先填充的核心数据数据库(.sqlite文件),而不是从存储在UserDefaults中的字符串进行预填充。我实现了这一点,在第一次本地启动时复制了捆绑的.sqlite文件之后,这个应用程序现在在本地运行良好。

但由于某种原因,这一更改导致CloudKit同步停止工作。现在,我不仅没有在其他设备上得到任何自动更新,而且在CloudKit仪表板遥测中也没有得到任何结果,因此CloudKit同步似乎永远不会开始。这很奇怪,因为在本地,我收到了刚刚在本地发生的“远程”更改的通知(当我在本地保存新数据时,将在本地调用作为通知的#选择器的函数)。

我对问题/解决办法感到困惑。这是我的相关代码。

代码语言:javascript
复制
//In my CoreDataHelper class
lazy var context = persistentContainer.viewContext

lazy var persistentContainer: NSPersistentCloudKitContainer = {

    let appName = Bundle.main.infoDictionary!["CFBundleName"] as! String
    let container = NSPersistentCloudKitContainer(name: appName)
    
    //Pre-load my default Core Data data (Category names) on first launch
    let storeUrl = FileManager.default.urls(for: .applicationSupportDirectory, in:.userDomainMask).first!.appendingPathComponent(appName + ".sqlite")
    let storeUrlFolder = FileManager.default.urls(for: .applicationSupportDirectory, 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"))
    }

    let storeDescription = NSPersistentStoreDescription(url: storeUrl)
    storeDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)

    //In the view controllers, we'll listen for relevant remote changes
    let remoteChangeKey = "NSPersistentStoreRemoteChangeNotificationOptionKey"
    storeDescription.setOption(true as NSNumber, forKey: remoteChangeKey)

    container.persistentStoreDescriptions = [storeDescription]
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    
    //This is returning nil but I don't think it should
    print(storeDescription.cloudKitContainerOptions?.containerIdentifier)
    
    return container
}()

//In my view controller

let context = CoreDataHelper.shared.context

override func viewDidLoad() {
    super.viewDidLoad()
    
    //Do other setup stuff, removed for clarity
    
    //enable CloudKit syncing
    context.automaticallyMergesChangesFromParent = true
}

override func viewWillAppear(_ animated: Bool) {
    clearsSelectionOnViewWillAppear = splitViewController!.isCollapsed
    super.viewWillAppear(animated)
    
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(reportCKchange),
        name: NSNotification.Name(
            rawValue: "NSPersistentStoreRemoteChangeNotification"),
        object: CoreDataHelper.shared.persistentContainer.persistentStoreCoordinator
    )
    updateUI()
}

@objc
fileprivate func reportCKchange() {
    print("Change reported from CK")
    tableView.reloadData()
}

注意:我已经将目标更新为iOS13+。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-07-13 08:26:52

我认为新创建的NSPersistentStoreDescription默认没有cloudKitContainerOptions

要设置它们,请尝试:

storeDescription.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: <<Your CloudKit ID>>)

票数 4
EN

Stack Overflow用户

发布于 2021-02-08 11:22:30

我还发现,实体的所有属性都必须是可选的,或者具有默认值,否则就无法工作。如果这份文件更清楚的话.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62867718

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档