Core Data + Cloud Kit:数据记录类型未显示在CloudKit控制台
问题描述
在Xcode中创建SwiftUI空白项目,勾选Core Data和Cloud Kit选项,使用Apple默认提供的NSPersistentCloudKitContainer代码(时间戳记录列表示例)。本地Core Data功能正常,但CloudKit控制台私有数据库仅显示"Users"记录类型,无应用数据记录类型。日志提示CloudKit集成失败,"Failed to sync user keys"(用户密钥同步失败)。
操作流程:
- 严格遵循官方Core Data+CloudKit配置教程
- 创建项目时勾选Core Data和Cloud Kit
- 未修改任何示例代码与配置文件
- 配置自动签名、iCloud(含CloudKit容器)、后台远程通知
- 模拟器登录Apple ID并添加时间戳,本地数据持久化正常
默认Persistent容器代码
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: "ProjectName") if inMemory { container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") } container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) container.viewContext.automaticallyMergesChangesFromParent = true } }
错误日志详情(已翻译)
CoreData: debug: CoreData+CloudKit: -[PFCloudKitOptionsValidator validateOptions:andStoreOptions:error:](36): 验证选项: <NSCloudKitMirroringDelegateOptions: 0x600003fd45a0> containerIdentifier:iCloud.com.ProjectName databaseScope:Private ckAssetThresholdBytes:<null> operationMemoryThresholdBytes:<null> useEncryptedStorage:NO useDeviceToDeviceEncryption:NO automaticallyDownloadFileBackedFutures:NO automaticallyScheduleImportAndExportOperations:YES skipCloudKitSetup:NO preserveLegacyRecordMetadataBehavior:NO useDaemon:YES apsConnectionMachServiceName:<null> containerProvider:<PFCloudKitContainerProvider: 0x600000fdc150> storeMonitorProvider:<PFCloudKitStoreMonitorProvider: 0x600000fdc1b0> metricsClient:<PFCloudKitMetricsClient: 0x600000fdc1f0> metadataPurger:<PFCloudKitMetadataPurger: 0x600000fdc200> scheduler:<null> notificationListener:<null> containerOptions:<null> defaultOperationConfiguration:<null> progressProvider:<NSPersistentCloudKitContainer: 0x6000018cd340> test_useLegacySavePolicy:YES archivingUtilities:<PFCloudKitArchivingUtilities: 0x600000fdc210> storeOptions: { NSInferMappingModelAutomaticallyOption = 1; NSMigratePersistentStoresAutomaticallyOption = 1; NSPersistentCloudKitContainerOptionsKey = "<NSPersistentCloudKitContainerOptions: 0x6000003a4000>"; NSPersistentHistoryTrackingKey = 1; NSPersistentStoreMirroringOptionsKey = { NSPersistentStoreMirroringDelegateOptionKey = "<NSCloudKitMirroringDelegate: 0x6000036d0340>"; }; } CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate observeChangesForStore:inPersistentStoreCoordinator:](385): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 监听存储: <NSSQLCore: 0x14d504650> (URL: file:///ADDRESS/PROJECT.sqlite) CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _setUpCloudKitIntegration](530): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 成功加入初始化请求队列。 CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest](2928): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 检查待处理请求。 CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest]_block_invoke(2941): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 执行请求: <NSCloudKitMirroringDelegateSetupRequest: 0x600001885e40> C5E6C108-29AD-4B29-B2F2-2E7B6CF17C43 CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](446): 跳过'ANSCKDATABASEMETADATA'迁移,因为已存在列'ZLASTFETCHDATE' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](503): 跳过'ANSCKMETADATAENTRY'迁移,因为已存在列'ZDATEVALUE' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](446): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZLASTFETCHDATE' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](462): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZSUPPORTSFETCHCHANGES' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](462): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZSUPPORTSATOMICCHANGES' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](462): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZSUPPORTSRECORDSHARING' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](462): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZSUPPORTSZONESHARING' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZNEEDSIMPORT' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZNEEDSRECOVERYFROMZONEDELETE' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZNEEDSRECOVERYFROMUSERPURGE' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZENCODEDSHAREDATA' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZNEEDSSHAREUPDATE' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZNEEDSSHAREDELETE' CoreData: debug: CoreData+CloudKit: -[PFCloudKitMetadataModelMigrator calculateMigrationStepsWithConnection:error:](479): 跳过'ANSCKRECORDZONEMETADATA'迁移,因为已存在列'ZNEEDSRECOVERYFROMIDENTITYLOSS' CoreData: CloudKit: CoreData+CloudKit: -[PFCloudKitSetupAssistant _checkUserIdentity:]_block_invoke(1235): <PFCloudKitSetupAssistant: 0x6000029c2880>: CKIdentity记录匹配存储: <CKRecordID: 0x600000dab560; recordName=_8b74d2123c870a6cd2fb07b5c74bb4b1, zoneID=_defaultZone:__defaultOwner__> 2022-09-25 11:06:51.874997+0800 ProjectName[19841:1140864] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1106): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 为存储设置CloudKit集成失败: <NSSQLCore: 0x14d504650> (URL: file:///ADDRESS/ProjectName.sqlite) <CKError 0x600000349440: "部分失败" (2/1011); "修改部分记录区失败"; 部分错误: { com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: "内部错误" (1/5000); "用户密钥同步失败"> }> CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _performSetupRequest:]_block_invoke(1106): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 为存储设置CloudKit集成失败: <NSSQLCore: 0x14d504650> (URL: file:///ADDRESS/PROJECT.sqlite) <CKError 0x600000349440: "部分失败" (2/1011); "修改部分记录区失败"; 部分错误: { com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: "内部错误" (1/5000); "用户密钥同步失败"> }> 2022-09-25 11:06:51.875077+0800 ProjectName[19841:1140864] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate recoverFromError:](2115): <NSCloudKitMirroringDelegate: 0x6000036d0340> - 尝试从错误恢复: <CKError 0x600000349440: "部分失败" (2/1011); "修改部分记录区失败"; 部分错误: { com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: "内部错误" (1/5000); "用户密钥同步失败"> }> CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate recoverFromError:](2115): <NSCloudKitMirroringDelegate: 0x6000036d0340> - 尝试从错误恢复: <CKError 0x600000349440: "部分失败" (2/1011); "修改部分记录区失败"; 部分错误: { com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: "内部错误" (1/5000); "用户密钥同步失败"> }> 2022-09-25 11:06:51.875317+0800 ProjectName[19841:1140864] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _recoverFromPartialError:forStore:inMonitor:]_block_invoke(2464): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 在部分失败中发现未知错误: <CKError 0x6000003b0390: "内部错误" (1/5000); "用户密钥同步失败"> CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _recoverFromPartialError:forStore:inMonitor:]_block_invoke(2464): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 在部分失败中发现未知错误: <CKError 0x6000003b0390: "内部错误" (1/5000); "用户密钥同步失败"> CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _finishedRequest:withResult:](2959): 请求完成: <NSCloudKitMirroringDelegateSetupRequest: 0x600001885e40> C5E6C108-29AD-4B29-B2F2-2E7B6CF17C43,结果: <NSCloudKitMirroringResult: 0x600000d8e7e0> success: 0 madeChanges: 0 error: <CKError 0x600000349440: "部分失败" (2/1011); "修改部分记录区失败"; 部分错误: { com.apple.coredata.cloudkit.zone:__defaultOwner__ = <CKError 0x6000003b0390: "内部错误" (1/5000); "用户密钥同步失败"> }> CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest](2928): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 检查待处理请求。 CoreData: CloudKit: CoreData+CloudKit: -[NSCloudKitMirroringDelegate checkAndExecuteNextRequest]_block_invoke(2944): <NSCloudKitMirroringDelegate: 0x6000036d0340>: 无待执行请求。
排查与解决建议
验证Apple ID状态
确保模拟器/设备登录的Apple ID已开启iCloud同步,测试账号需确认开发者权限正常;尝试退出重新登录Apple ID,同时清除模拟器缓存(Hardware > Erase All Content and Settings)。核对CloudKit容器配置
确认Xcode项目中iCloud配置的容器ID与CloudKit控制台的容器ID完全一致(注意iCloud.前缀、大小写);检查控制台中容器私有数据库的读写权限是否对当前用户开放。检查项目签名与权限
确认自动签名使用的开发者账号拥有CloudKit权限;项目Capabilities中需勾选iCloud的CloudKit选项并关联正确容器,同时开启后台模式的"Remote notifications";清理项目缓存(Product > Clean Build Folder)后重新编译运行。重置本地Core Data存储
删除本地SQLite文件(路径可从日志URL定位),让Core Data重新初始化并同步CloudKit;或临时修改PersistenceController初始化逻辑,清空存储后恢复。确认网络环境
CloudKit需稳定外网连接,避免代理、防火墙拦截Apple服务器请求。
内容的提问来源于stack exchange,提问作者Sanjo

