You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSPersistentCloudKitContainer触发CKErrorDomain 12后同步终止,求排查修复方案

CoreData + CloudKit 同步错误 CKErrorDomain 12 排查求助

我用NSPersistentCloudKitContainer实现了CoreData与iCloud的数据同步,近期收到线上用户反馈同步失败,错误码为CKErrorDomain 12。

我通过NSPersistentCloudKitContainer.eventChangedNotification监听同步状态,代码如下:

NotificationCenter.default.publisher(for: NSPersistentCloudKitContainer.eventChangedNotification)
            .sink(receiveValue: { notification in
                if let cloudEvent = notification.userInfo?[NSPersistentCloudKitContainer.eventNotificationUserInfoKey]
                    as? NSPersistentCloudKitContainer.Event {
                    let event = SyncEvent(from: cloudEvent) 
                }
            })
            .store(in: &disposables)

用户反馈同步失败时,能看到是CoreData+iCloud导出数据出错,但cloudKitEvent.error仅包含CKErrorDomain 12,没有更多详细信息,根本没法排查问题。

更严重的是,触发这个错误后,应用的同步服务会直接停止,不管是重启App、重启手机还是关闭系统里的iCloud同步,都没法恢复同步功能,只有卸载重装应用才能彻底解决,但这样会导致用户本地未同步的数据丢失。

我的CoreDataStack初始化代码如下:

private func setupContainer(allowCloudKitSync: Bool) -> NSPersistentCloudKitContainer {
    let container = NSPersistentCloudKitContainer(name: containerName)
    let privateStoreURL = containerURL.appendingPathComponent(privateStoreName)
    let privateDescription = NSPersistentStoreDescription(url: privateStoreURL)
    let privateOpt = NSPersistentCloudKitContainerOptions(containerIdentifier: identifier)
    
    privateDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    privateDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
    
    "allowCloudKitSync = \(allowCloudKitSync)".debugLog("CoreDataStack")
    
    if allowCloudKitSync {
        privateDescription.cloudKitContainerOptions = privateOpt
    } else {
        privateDescription.cloudKitContainerOptions = nil
    }

    container.persistentStoreDescriptions = [privateDescription]
    
    container.loadPersistentStores(completionHandler: { [weak self] (storeDescription, error) in
        if let error = error as NSError? {
            self?.dbStatePublish.send(.loadError)
            #if DEBUG
            "Unresolved error \(error), \(error.userInfo)".debugLog("CoreDataStack")
            #endif
        } else {
            if storeDescription.cloudKitContainerOptions == nil {
                self?.coreDataState = .local
            } else {
                self?.coreDataState = .cloud
            }

            "load coredata status = \(String(describing: self?.coreDataState))".debugLog("CoreDataStack")
        }
    })
    
    //let options = NSPersistentCloudKitContainerSchemaInitializationOptions()        
    //try? container.initializeCloudKitSchema(options: options)

    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    container.viewContext.transactionAuthor = appTransactionAuthorName

    // Pin the viewContext to the current generation token and set it to keep itself up to date with local changes.
    container.viewContext.automaticallyMergesChangesFromParent = true
    do {
        try container.viewContext.setQueryGenerationFrom(.current)
    } catch {
        fatalError("###\(#function): Failed to pin viewContext to the current generation:\(error)")
    }
    
    // Observe Core Data remote change notifications.
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(storeRemoteChange(_:)),
                                           name: .NSPersistentStoreRemoteChange,
                                           object: container.persistentStoreCoordinator)
    
    return container
}

有没有人遇到过类似的问题?求帮忙排查,谢谢!

内容的提问来源于stack exchange,提问作者wanbo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 04:55:00