在 watchOS 上使用 CloudKit 的 CoreData 不同步

shi*_*dul 10 core-data ios cloudkit watchos-6 nspersistentcloudkitcontainer

我已经设法让 CoreData 与 CloudKit 一起使用我的应用程序的 iOS 版本上的新 NSPersistentCloudKitContainer 并让它在应用程序运行时自动同步。但是,当我在 watchOS 应用程序上进行设置时,我注意到只有在我强制关闭并重新打开手表应用程序时才会发生同步。

import Foundation
import CoreData

class DataManager : NSObject {
    static let shared = DataManager()

    #if os(watchOS)
    let transactionAuthorName = "watchOSApp"
    #else
    let transactionAuthorName = "iOSApp"
    #endif

    override private init() {
        super.init()
    }

    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentCloudKitContainer(name: "Model")

        let cloudStoreUrl = applicationDocumentDirectory()!.appendingPathComponent("product.sqlite")

        let cloudStoreDescription = NSPersistentStoreDescription(url: cloudStoreUrl)
        cloudStoreDescription.shouldInferMappingModelAutomatically = true
        cloudStoreDescription.shouldMigrateStoreAutomatically = true
        cloudStoreDescription.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier:"iCloud.com.company.product")

        container.persistentStoreDescriptions = [cloudStoreDescription]

        container.loadPersistentStores(completionHandler: { storeDescription, error in
            if let error = error as NSError? {
                print("Error loading store. \(error)")
            }
        })

        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        container.viewContext.automaticallyMergesChangesFromParent = true

        try? container.viewContext.setQueryGenerationFrom(.current)
        container.viewContext.transactionAuthor = transactionAuthorName

        return container
    }()
}

// MARK: - Core Data
extension DataManager {

    func applicationDocumentDirectory() -> URL? {
        return FileManager.default.containerURL(forSecurityApplicationGroupIdentifier:"group.shiningdevelopers.h2o")
    }

    func managedObjectContext() -> NSManagedObjectContext {
        return persistentContainer.viewContext
    }

    func reset() {
        managedObjectContext().reset()
    }

    func saveContext () {
        let context = managedObjectContext()
        if context.hasChanges {
            do {
                try context.save()
            } catch let error as NSError {
                // Replace this implementation with code to handle the error appropriately.
                // Log this error for now to be able to glean more information
                print("Could not save. \(error), \(error.userInfo)")
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以下场景有效 - 用户同时运行 watchOS 应用程序和 iOS 应用程序 - 用户更改手表应用程序上的数据 - 更改反映在 iOS 应用程序上 - 用户仅运行 iOS 应用程序 - 用户更改为iOS 应用程序上的数据 - 用户从终止状态打开 watchOS 应用程序 - 更改反映在 watchOS 应用程序上

以下场景不起作用 - 用户运行 watchOS 应用程序并且运行 iOS 应用程序 - 用户更改 iOS 应用程序上的数据 - 即使等待很长时间,也没有更改传递到 watchOS 应用程序 - 只有如果我强制关闭应用程序并重新启动会发生同步

在同步成功的情况下,我会正确看到以下日志:

CoreData: debug: CoreData+CloudKit: 
-[PFCloudKitImporterZoneChangedWorkItem newMirroringResultByApplyingAccumulatedChanges:]_block_invoke_2(243): <PFCloudKitImporterZoneChangedWorkItem: 0x16530fb0> { ( "<CKRecordZoneID: 0x1656a920; zoneName=com.apple.coredata.cloudkit.zone, ownerName=__defaultOwner__>" ) } - Importing updated records: ( "<CKRecord: 0x16526280; recordType=CD_LogEntry, values={\n "CD_day" = 15;\n "CD_entityName" = LogEntry;\n "CD_glassesGoal" = 8;\n "CD_glassesLogged" = 13;\n "CD_lastModified" = "2019-09-15 18:56:08 +0000";\n "CD_month" = 9;\n "CD_year" = 2019;\n}, recordChangeTag=7d, recordID=2180D6A3-ACFC-4421-8CAF-6EE288DAAC2E:(com.apple.coredata.cloudkit.zone:defaultOwner)>" ) Deleted RecordIDs: {
}
Run Code Online (Sandbox Code Playgroud)

然而,在最后一个场景中,我没有看到任何日志,它完全安静。我在应用程序的 iOS 和 watchOS 版本中共享相同的 CoreData/CloudKit 代码。我还使用 NSFetchedResultsController 来确保我的 UI 保持最新状态,它似乎在 iOS 应用程序上运行,但在 watchOS 应用程序上不起作用。不确定在设置手表扩展时是否遗漏了某些步骤。

有没有人同步到 watchOS 来工作?任何帮助,将不胜感激。

小智 1

您是否尝试过添加一个观察者,例如:

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

然后观察观察者的变化并在那时进行 UI 更新?