如何排队大量入站 CloudKit 通知
Posted
技术标签:
【中文标题】如何排队大量入站 CloudKit 通知【英文标题】:How to Queue Up Lots of Inbound CloudKit Notifications 【发布时间】:2018-08-05 06:17:04 【问题描述】:假设我使用CKModifyRecordsOperation
将 50 条记录保存到 CloudKit,如下所示:
let operation = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: nil)
operation.savePolicy = .changedKeys
operation.modifyRecordsCompletionBlock = records, _, error in
//...
privateDB.add(operation)
在我的其他设备上,每更改一个 CKRecord
,我都会收到 50 条不同的背景通知。没关系,我期待。
我这样处理每个入站通知:
func processCloudKitNotification(notification: CKNotification, database: CKDatabase)
guard let notification = notification as? CKQueryNotification else return
if let recordID = notification.recordID
var recordIDs = [CKRecordID]()
switch notification.queryNotificationReason
case .recordDeleted:
//Delete [-]
//...
default:
//Add and Edit [+ /]
recordIDs.append(recordID)
let fetchOperation = CKFetchRecordsOperation(recordIDs: recordIDs)
fetchOperation.fetchRecordsCompletionBlock = records, error in
//...
database.add(fetchOperation)
但由于 50 个传入通知中的每一个都是单独的事件,因此该函数会被调用 50 次不同的时间,因此会触发大量使用通知给我的CKRecordID
s 来拉取完整记录的请求。
如何在合理的时间内将所有传入的通知CKRecordID
s 排队,以便我可以一次使用多个记录ID 发出更有效的CKFetchRecordsOperation
请求?
【问题讨论】:
您是否真的在短时间内收到了 50 条通知?这些不应该合并吗?使用 CKFetchRecordZoneChangesOperation 怎么样? 我不确定通知是否应该合并。我很确定他们不会,因为后台推送的有效负载非常小。我在我的应用程序的其他地方使用了CKFetchRecordZoneChangesOperation
,但是当回复CKNotification
时,我得到了CKRecordID
的更改内容,因此获取其相应记录似乎是有意义的。
【参考方案1】:
我最终为此使用了一个计时器,而且效果很好。基本上我会在收到新的推送通知时启动一个计时器,并在每次收到其他通知时重置它。同时,我收集所有传入的CKRecordID
,然后在计时器触发时处理它们(这发生在通知停止流入之后)。
这是我的代码:
var collectNotificationsTimer: Timer?
var recordIDsFromNotifications = [CKRecordID]()
func processCloudKitNotification(notification: CKNotification, database: CKDatabase)
guard let notification = notification as? CKQueryNotification else return
guard let recordID = notification.recordID else return
//:: 1 :: Collect record IDs from incoming notifications
if notification.queryNotificationReason == .recordDeleted
//Delete [-]
//...
else
//Add and Edit [+ /]
recordIDsFromNotifications.append(recordID)
//:: 2 :: After collecting IDs for 1 second, request a batch of updated records
collectNotificationsTimer?.invalidate()
collectNotificationsTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: false) _ in
let fetchOperation = CKFetchRecordsOperation(recordIDs: recordIDsFromNotifications)
fetchOperation.fetchRecordsCompletionBlock = records, error in
recordIDsFromNotifications.removeAll()
if let error = error
checkCloudKitErrorAndRetryRequest(name: "fetchRecordsCompletionBlock", error: error)
else
if let records = records
//Save records...
database.add(fetchOperation)
【讨论】:
以上是关于如何排队大量入站 CloudKit 通知的主要内容,如果未能解决你的问题,请参考以下文章
Swift CloudKit CoreData 远程更改通知也会触发本地更改