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

在共享记录上使用CKQuerySubscription无法接收通知问题

解决CloudKit共享记录订阅真机收不到通知的问题

针对你遇到的订阅成功但真机无通知的问题,按以下步骤排查修正:

1. 修正数据库实例

订阅共享记录的变更必须使用共享数据库(sharedCloudDatabase),而非私有数据库。私有数据库的订阅无法监听共享库内的记录变更,把代码里的privateCloudDatabase换成sharedCloudDatabase:

let sharedDB = PersistenceManager.shared.ckContainer.sharedCloudDatabase

2. 完善推送权限与后台配置

  • 真机前往「设置→对应App→通知」确认通知权限已开启
  • 项目Signing & Capabilities中:
    • 开启Push Notifications能力,确保推送证书与CloudKit环境(开发/生产)匹配
    • 开启Background Modes,勾选Remote notifications(否则shouldSendContentAvailable = true的静默通知无法触发后台回调)
  • 确保App启动时请求了通知权限并注册远程通知:
    // 在didFinishLaunchingWithOptions中添加
    UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
        if granted {
            DispatchQueue.main.async {
                UIApplication.shared.registerForRemoteNotifications()
            }
        }
    }
    UNUserNotificationCenter.current().delegate = self
    

3. 优化订阅范围与谓词

避免用NSPredicate(value: true)订阅所有同类型记录,缩小范围到当前群组的共享记录,提升精准度:

guard let shareRecordID = group.share?.recordID else { return }
let predicate = NSPredicate(format: "recordID == %@", shareRecordID)

4. 修正通知回调处理

如果是静默通知(shouldSendContentAvailable = true),需使用正确的回调方法:

  • iOS 10+ 优先用UNUserNotificationCenterDelegate的userNotificationCenter(_:didReceive:withCompletionHandler:)
  • 旧版回调需用application(_:didReceiveRemoteNotification:fetchCompletionHandler:),而非单纯的didReceiveRemoteNotification

5. 环境与测试场景验证

  • 确保CloudKit控制台的环境(Development/Production)与真机测试环境一致
  • 用另一个iCloud账号修改共享记录测试,避免当前用户自身修改导致的本地同步屏蔽通知

修正后的完整订阅代码示例

func createQuerySubscription(_ group: ExpensesGroup) async {
    let sharedDB = PersistenceManager.shared.ckContainer.sharedCloudDatabase

    guard let shareRecordID = group.share?.recordID else { 
        print("无法获取共享记录ID")
        return 
    }
    let predicate = NSPredicate(format: "recordID == %@", shareRecordID)
    
    let subscriptionID = "\(group.id ?? "")_share_sub"
    let shareSubscription = CKQuerySubscription(
        recordType: "cloudkit.share",
        predicate: predicate,
        subscriptionID: subscriptionID,
        options: [.firesOnRecordCreation, .firesOnRecordDeletion, .firesOnRecordUpdate]
    )
    
    let notification = CKSubscription.NotificationInfo()
    notification.shouldSendContentAvailable = true
    notification.alertBody = "群组共享信息已更新" // 可选:前台显示通知提示
    
    shareSubscription.notificationInfo = notification
    
    let operation = CKModifySubscriptionsOperation(subscriptionsToSave: [shareSubscription])
    operation.modifySubscriptionsResultBlock = { result in
        switch result {
        case .success:
            print("共享记录订阅创建成功")
        case .failure(let error):
            print("订阅创建失败:\(error.localizedDescription)")
        }
    }
    operation.qualityOfService = .userInteractive
    
    sharedDB.add(operation)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:52:46