静默 iCloud 更改通知未在后台收到

Silent iCloud changed notifications not received in background

我的应用程序使用 public iCloud 数据库,该数据库使用推送通知进行同步。
订阅 iCloud 通知使用以下 notificationInfo

    let notificationInfo = CKNotificationInfo()
    notificationInfo.alertBody = nil
    notificationInfo.shouldSendContentAvailable = true  

测试设置使用 2 iOS 台设备:

第一次测试:

第二台设备:在前台执行我的应用程序。

当第一个设备修改数据库时,

收到通知
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) 

这符合预期。

第二次测试:

第二台设备:同上,但现在屏幕已关闭,即我的应用程序处于后台。

当第一个设备修改数据库时,收到通知。

预期行为:
由于 shouldSendContentAvailable 在通知信息中设置为 true,系统应该唤醒我的应用程序(请参阅 docs)。然后应为应用程序提供后台执行时间来下载与推送通知相关的任何数据,例如已更改的记录集。这应该通过调用

来完成
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)  

实际行为:
锁定屏幕中会显示一条警告,提示“iCloud 已更改,滑动打开”。如果我滑动此警报并解锁设备,此功能才会真正被调用。

我的问题:
我想使用来自 iCloud 的静默推送来更新我的应用程序的本地数据。那么,为什么在锁定屏幕上显示默认消息正文“iCloud 已更改”的警报,尽管我设置了 shouldSendContentAvailable = true

我的错,虽然不明显:

我的 CloudKit 仪表板显示有我的订阅类型。但出于某种原因,仪表板没有显示任何订阅。因此,我使用

获取了所有现有订阅
private func getAllSubscriptionIDs(completion: @escaping (_ subscriptionIDs:[String]?, _ error: Error?) -> Void) {
    let database = CKContainer.default().publicCloudDatabase
    database.fetchAllSubscriptions { subscriptions, error in
        guard error == nil else {
            completion(nil, error)
            return
        }
        guard let subscriptions = subscriptions else {
            completion([], nil)
            return
        }
        let subscriptionIDs = subscriptions.map{ [=10=].subscriptionID }
        completion(subscriptionIDs, nil)
    } // fetchAllSubscriptions
}  

我得到了 5 个现有订阅,其中一个有一个警告正文“iCloud changed”和 shouldSendContentAvailable = false

显然,我在开发的早期确实使用了这些订阅,但我没有删除它们,因为它们没有显示在仪表板中。
删除它们解决了问题。