CloudKit订阅异常:Settings实体缺失且Category订阅重复
CloudKit订阅注册异常问题排查
我通过以下代码为iCloud实体注册订阅:
let options: CKQuerySubscriptionOptions = [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion] let territoryGroupSubscription = CKQuerySubscription(recordType: "TerritoryGroup", predicate: NSPredicate(value: true), options: options) let serviceSubscription = CKQuerySubscription(recordType: "Service", predicate: NSPredicate(value: true), options: options) let goalSubscription = CKQuerySubscription(recordType: "Goal", predicate: NSPredicate(value: true), options: options) let territorySubscription = CKQuerySubscription(recordType: "Territory", predicate: NSPredicate(value: true), options: options) let addressSubscription = CKQuerySubscription(recordType: "Address", predicate: NSPredicate(value: true), options: options) let noteSubscription = CKQuerySubscription(recordType: "Note", predicate: NSPredicate(value: true), options: options) let daySubscription = CKQuerySubscription(recordType: "Day", predicate: NSPredicate(value: true), options: options) let categorySubscription = CKQuerySubscription(recordType: "Category", predicate: NSPredicate(value: true), options: options) let shareSubscription = CKQuerySubscription(recordType: "cloudkit.share", predicate: NSPredicate(value: true), options: options) let settingsSubscription = CKQuerySubscription(recordType: "Settings", predicate: NSPredicate(value: true), options: options) let notificationInfo = CKNotificationInfo() notificationInfo.shouldBadge = false notificationInfo.shouldSendContentAvailable = true territoryGroupSubscription.notificationInfo = notificationInfo serviceSubscription.notificationInfo = notificationInfo goalSubscription.notificationInfo = notificationInfo territorySubscription.notificationInfo = notificationInfo addressSubscription.notificationInfo = notificationInfo noteSubscription.notificationInfo = notificationInfo daySubscription.notificationInfo = notificationInfo categorySubscription.notificationInfo = notificationInfo shareSubscription.notificationInfo = notificationInfo settingsSubscription.notificationInfo = notificationInfo let privateSubscriptionsOperation = CKModifySubscriptionsOperation(subscriptionsToSave: [settingsSubscription, territoryGroupSubscription, serviceSubscription, goalSubscription, territorySubscription, addressSubscription, noteSubscription, daySubscription, categorySubscription, shareSubscription], subscriptionIDsToDelete: nil) privateSubscriptionsOperation.database = CloudAssistant.shared.privateDatabase let queue = OperationQueue() queue.maxConcurrentOperationCount = 1 queue.addOperation(privateSubscriptionsOperation)
问题现象
在CloudKit控制台中可见共有10个订阅,但Category记录类型的订阅出现重复,Settings记录类型的订阅缺失。删除控制台中所有订阅后重新注册,仅生成9个订阅,Settings订阅仍未出现。
问题原因及排查方向
1. Settings是否为系统保留名称?
CloudKit官方并未公开将Settings列为系统保留记录类型名称,但存在两种隐性可能性:
- 苹果对部分高频通用名称有隐性限制,
Settings可能因与系统服务逻辑冲突,被服务器拦截订阅请求 - 自定义记录类型配置异常:若CloudKit控制台中
Settings记录类型未正确创建、私有数据库权限未开启,或字段配置存在错误,会导致订阅请求被忽略
2. 重复订阅与缺失订阅的核心原因
- 自动生成ID冲突:未手动指定
subscriptionID时,系统会自动生成ID,若代码重复执行注册逻辑,可能导致Category订阅重复;而Settings订阅可能因记录类型异常,被系统直接丢弃请求 - 异步操作未捕获错误:
CKModifySubscriptionsOperation是异步操作,当前代码未添加完成回调,无法确认Settings订阅是否保存失败,也无法获取具体错误信息 - 数据库匹配错误:需确认
CloudAssistant.shared.privateDatabase确实指向私有数据库,若Settings记录类型仅存在于共享数据库,私有库的订阅请求会被直接忽略 - 服务器缓存干扰:删除订阅后可能存在服务器缓存延迟,但多次重试后仍缺失则可排除此因素
3. 具体排查步骤
- 为每个订阅手动指定唯一
subscriptionID,避免自动生成ID的重复问题,同时方便控制台精准匹配:let settingsSubscription = CKQuerySubscription(recordType: "Settings", predicate: NSPredicate(value: true), subscriptionID: "Settings_All_Changes", options: options) let categorySubscription = CKQuerySubscription(recordType: "Category", predicate: NSPredicate(value: true), subscriptionID: "Category_All_Changes", options: options) - 添加操作完成回调,捕获错误并排查未成功保存的订阅:
privateSubscriptionsOperation.modifySubscriptionsCompletionBlock = { savedSubscriptions, deletedIDs, error in if let error = error { print("订阅保存失败:\(error.localizedDescription)") let savedIDs = savedSubscriptions?.map { $0.subscriptionID } ?? [] let expectedIDs = ["Settings_All_Changes", "Category_All_Changes", "TerritoryGroup_All_Changes"] // 补充所有订阅ID let missingIDs = expectedIDs.filter { !savedIDs.contains($0) } print("未成功保存的订阅:\(missingIDs)") } } - 检查CloudKit控制台中
Settings记录类型的配置:确认记录类型存在、私有数据库权限开启、无字段验证规则阻止订阅 - 单独注册Settings订阅,排除其他订阅的干扰,验证是否能成功创建
- 查看Xcode CloudKit调试日志:在
Window > Devices and Simulators中选择设备,打开Console过滤CloudKit关键字,查找与Settings订阅相关的错误信息
内容的提问来源于stack exchange,提问作者kunass2
相关产品推荐
相关产品推荐

