CloudKit 不发送更新通知

Posted

技术标签:

【中文标题】CloudKit 不发送更新通知【英文标题】:CloudKit Not Sending Update Notifications 【发布时间】:2016-10-07 08:04:31 【问题描述】:

我正在尝试开发一个简单的消息应用程序来学习 CloudKit 的基础知识。

我已经差不多搞定了,只是我无法接收记录更新事件的通知。

为了测试应用程序,我在设备和模拟器上同时运行它。

两个实例都登录到同一个 iCloud 帐户(还没有创建专用帐户进行测试...);但是,该应用使用 UUIds 区分本地用户和远程用户,所以这不是问题。

当应用程序的一个实例想要发送消息时,它会创建一条记录并将其保存到 CloudKit。

我知道模拟器不支持 APN,但如果我从模拟器发送消息,我可以在设备上收到通知。

这行得通。


接下来,我想将消息标记为“已读”:也就是说,当它们第一次显示在不是它们的作者的设备上时,标记它们。

我通过获取相应的记录、修改它并保存它来做到这一点。因此,我从设备发送的消息显示在模拟器上,并在那里标记为“已读”。我将更改与 cloudKit 同步并希望设备收到通知

publicDatabase.perform(query, inZoneWith: nil, completionHandler: (records, error) in

    guard let records = records, records.count > 0 else 
        return print("Error - Message: \(message.text) by \(message.userName) NOT found on the cloud!")   
    
    let record = records[0]

    // HERE THE RECORD IS MODIFIED LOCALLY:    
    record["readTimestamp"] = (message.readTimestamp! as NSDate)

    // Now, save it:     
    self.publicDatabase.save(record, completionHandler: record, error in
        guard error == nil else 
            return print("Error - Message: \(message.text) by \(message.userName) could NOT be saved as read!")
        
        print("Message: \(message.text) by \(message.userName) SAVED as read at \(message.readTimestamp!)")
    )
) 

但是,在另一端,从未收到“更新”通知。

是因为两个实例都以同一用户身份登录 iCloud 吗?我觉得这很难相信,因为“创建”通知交付时没有问题。

两种通知(“消息创建”和“消息更新”)的订阅都已成功注册,并显示在 CloudKit 仪表板上(触发器 INSERTUPDATE)。


更新:经过很长时间思考我的“创建”订阅和我的“更新”订阅之间可能有什么不同,这可能会导致其中一个触发通知,我意识到只有“创建”订阅有一个通知正文:

let subscription = CKQuerySubscription(recordType: "Message",
        predicate: NSPredicate(value: true),
        subscriptionID: Bundle.main.bundleIdentifier! + ".subscription.message.create",
        options: .firesOnRecordCreation
    )

    let notificationInfo = CKNotificationInfo()

    // THIS LINE MAKES ALL THE DIFFERENCE:
    notificationInfo.alertBody = "You've Got Mail!"

    subscription.notificationInfo = notificationInfo

    publicDatabase.save(subscription, completionHandler: savedSubscription, error in

...而“更新”订阅没有:

    let notificationInfo = CKNotificationInfo()
    subscription.notificationInfo = notificationInfo

添加警报正文后,“更新”通知开始到达。

但是,这只是一种解决方法:我需要 静默 通知我的阅读更新。显示横幅只是为了提醒用户他的消息已在另一端阅读是没有意义的。 另外,CloudKit 编程指南也没有提到这个限制。

有没有办法订阅静默(即空)推送通知?


更新 2: 实际上,我在 API Reference 上为 CKNotificationInfo 找到了这个位:

注意

如果您未设置任何 alertBodysoundNameshouldBadge 属性,推送通知以较低的优先级发送 不会导致系统提醒用户。

(强调我的)

我仍然看不出这个“不会导致系统提醒用户的较低优先级”如何等同于“application(:didReceiveRemoteNotification:fetchCompletionHandler:)根本没有被调用”。

【问题讨论】:

你找到解决办法了吗? 并非如此。这是一个爱好项目,从那以后我一直忙于工作。 【参考方案1】:

解决方案似乎是使用带有shouldSendContentAvailable = true 的信息对象,如下所示:

let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
subscription.notificationInfo = info

这已经为我解决了。它会导致didReceiveRemoteNotification: 触发,而不会出现任何用户可见的通知。所以它是一个无声的通知,正如所愿,它实际上是如愿到达的。

如果我离开subscription.notificationInfo nil,则应用程序永远不会收到更改通知。但是使用 [有效沉默] 信息对象,我得到了想要的结果。

【讨论】:

我发现如果我也设置一个空白alertBody 像这样:info.alertBody = "",我在后台推送方面的可靠性更高。这有助于以更高的优先级发送推送,但它仍然会以静默方式到达。

以上是关于CloudKit 不发送更新通知的主要内容,如果未能解决你的问题,请参考以下文章

如何创建 CloudKit 订阅通知以触发记录属性更新?

如何通知另一台设备 CloudKit 记录已更新?

CloudKit 通知未发送到所有设备

记录更新的 CloudKit 推送通知停止工作

swift Swift - CloudKit - 处理更新记录的通知

使用 CloudKit 延迟后触发推送通知