CKReference 的 CloudKit 订阅通知未按预期工作
Posted
技术标签:
【中文标题】CKReference 的 CloudKit 订阅通知未按预期工作【英文标题】:CloudKit Subscription Notification for CKReference Not Working As Expected 【发布时间】:2015-04-22 01:14:54 【问题描述】:我正在尝试为包含具有用户 CKReference 的字段的记录设置 CKSubscription。但无论何时创建记录,它都会忽略复合谓词的这一部分,并且永远不会收到通知。在 CKSubscription 的谓词中使用 CKReference 有什么不同吗?我进入仪表板以在我自己的用户 recordID 下输入新记录(在模拟器中运行另一个用户时),因为我相信我读到如果记录来自设备,它将不会收到通知。非常感谢任何见解,因为我已经坚持了一周并且无法在网上找到任何特定于此的内容。我能够获得真实类型的谓词通知,所以我认为我的基本设置还可以。
在仪表板中,我看到两个测试用户都有一个通用订阅,但没有任何一个用户的特定记录 ID(这有关系吗?):
Notifications.read (equals string)
Notifications.user (equals reference)
当我执行 fetchAllSubscriptionsWithCompletionHandler 方法时,它会在调试器中将当前用户对此设备的特定记录 ID 显示为 CKReference。所以我不知道为什么它不起作用。
这是我的代码,我首先创建 CKReference,然后将其用于我的谓词:
var recordIDString = CKRecordID(recordName: "_a86dac8ee05f8c6ab35746bf9663d7b8")
// I normally store this string in the NSUserDefaults.
let userRef = CKReference(recordID: recordIDString, action: .DeleteSelf)
let predicate = NSPredicate(format: "user = %@", userRef)
let predicateTwo = NSPredicate(format: "read = %@", "")
// I want the read field to be empty, which tells me user has not read my internal app notif.
let compoundPred = NSCompoundPredicate(type: .AndPredicateType, subpredicates: [predicate, predicateTwo])
Now I set-up the subscription like this:
let subscription = CKSubscription(recordType: "Notifications",
predicate: compoundPred,
options: .FiresOnRecordCreation)
let notificationInfo = CKNotificationInfo()
notificationInfo.alertBody = "Someone replied to your post"
notificationInfo.shouldBadge = true
subscription.notificationInfo = notificationInfo
publicDB.saveSubscription(subscription,
completionHandler: (subscription, error in.....etc)
// handling this part
【问题讨论】:
我认为 CloudKit 不适用于复合谓词。我想我在某处读到过它,但找不到精确的链接。但我发现了一个关于这个问题的 rdar:openradar.me/18807663 谢谢@flinth。我已经有一段时间没有重新审视这一点来确认了,但这令人失望。 【参考方案1】:我遇到了同样的问题,偶然发现了苹果网站上的这条信息:
在创建谓词包含 CKReference 字段的订阅时,请务必在创建谓词时使用 CKRecordID 对象作为该字段的值。在这种情况下使用 CKRecord 对象目前不起作用。
当我将 CKQuerySubscription 的谓词更改为使用 CKRecordID 而不是 CKReference 时,它按预期工作。我意识到这是一个旧线程,但我很难找到这个问题的答案,因为谓词在 CKQuery 和 CKQuerySubscription 之间的行为似乎不同。
【讨论】:
抱歉延迟回复。谢谢(你的)信息。实际上,我已经离开 Cloudkit 一段时间了,最近一直在使用 Firebase。但是,如果我需要回到 Cloudkit,这很高兴知道。谢谢! @ReneeOlson 没问题,不客气 - 这绝对不是很直观,所以希望这可以避免其他人不得不处理这个问题。 @Imperious 你有链接到它在苹果网站上讨论这个的地方吗?我仍然无法让它工作。 @CliftonLabrum 我看了一眼,但我似乎找不到它,也许他们已经更新了他们的文档。我过渡到 Firebase,所以过去一年我没有使用 CloudKit,但我明天会更深入地查看他们的文档,如果我没有找到任何东西,那么也许我可以找到我的代码来展示一个示例。很抱歉! 我终于可以让它工作了。如您所述,使用CKRecord
是正确的。我没有将我的记录指向正确的区域。一旦我这样做了,通知就开始工作了。谢谢!【参考方案2】:
使用NSPredicate
而不是NSCompoundPredicate
初始化您的订阅:
let predicate = NSPredicate(format: "user = %@ AND read = %@",
argumentArray: [userRef, ""])
let subscription = CKSubscription(recordType: "Notifications",
predicate: predicate,
options: .FiresOnRecordCreation)
根据我使用 CloudKit 的经验,这应该可以。
【讨论】:
谢谢@小胡子。我尝试了您的谓词,不幸的是推送通知从未出现。也许我测试错了,但我认为苹果说要测试通知是否来自仪表板。所以我使用不同的 iCloud 帐户启动应用程序并将其置于后台。然后我在仪表板中添加新记录。这是正确的吗?仪表板中使用谓词的订阅看起来与之前相同 - Notifications.read(等于字符串) Notifications.user(等于引用)。 从最新的 Xcode 版本开始,它的行为很奇怪 - 我不得不摆脱订阅 ID 并使用便利的 init,因为即使我在仪表板中删除了订阅,我第一次订阅它现在给错误 - “从类型 '_sub_trigger_sub_2ded4b5120b4a2aae398d61a681d5599' 到 '_sub_trigger_sub_f678ae78884bd7ce081d07cb60385af1' 的更新记录无效”; uuid = ....;容器 ID = ....” 但是,订阅位于仪表板中。之前,第一次它让我在删除它后使用相同的订阅 ID 订阅,第二次尝试给我错误,说它是重复的。 多么奇怪......现在错误行为突然停止并按预期工作。它给出了 3 次之前的错误。我开始怀疑我的计算机和我安装的 Xcode 是否存在问题。在删除订阅然后使用相同的订阅 ID 重新订阅后,您是否遇到过类似的错误? 因此,谓词(我的和你的)似乎有效,并且订阅在仪表板中,但推送通知永远不会发送给用户。这不是我的推送通知代码/设置的问题,因为我可以获得一个简单的“True”谓词来处理查询订阅。如果您或任何人可以复制我的问题,并且您同意我正在正确测试推送通知(第一条评论),那么这可能是一个 cloudkit 错误。问题是我找不到另一个一起使用订阅和引用的示例来验证我是否做错了什么。 由于 CloudKit 主要是一个黑匣子,所以很难说出幕后发生的事情。在尝试新方法之前,您是否尝试过重置开发环境?以上是关于CKReference 的 CloudKit 订阅通知未按预期工作的主要内容,如果未能解决你的问题,请参考以下文章
CloudKit - 在 CKRecord 中存储多个 CKReference
CloudKit 上的 CKReference 使用 Swift
CloudKit - NSPredicate 用于在引用列表中查找包含多个 CKReference 的所有记录