如何排队大量入站CloudKit通知

时间:2018-08-05 06:17:05

标签: swift apple-push-notifications cloudkit cknotification

假设我用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提取全部记录。< / p>

如何在合理的时间内将所有传入的通知CKRecordID排入队列,以便一次发出多个recordID来进行效率更高的CKFetchRecordsOperation请求?

1 个答案:

答案 0 :(得分:0)

我最终为此使用了一个计时器,并且效果很好。基本上,我会在收到新的推送通知时启动计时器,并在每次收到其他通知时将其重置。同时,我收集了所有进入的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)
    }
  }
}