0

假设我将 50 条记录保存到 CloudKit,CKModifyRecordsOperation如下所示:

let operation = CKModifyRecordsOperation(recordsToSave: records, recordIDsToDelete: nil)
operation.savePolicy = .changedKeys

operation.modifyRecordsCompletionBlock = { records, _, error in
    //...
}

privateDB.add(operation)

在我的其他设备上,我会收到50 个不同的背景通知,每一个都CKRecord发生了变化。没关系,我期待。

我像这样处理每个入站通知:

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)
  }
}

CKRecordID但是由于 50 个传入通知中的每一个都是单独的事件,因此该函数会被调用 50 次不同的时间,因此会触发大量请求以使用通知给我的 s 来拉取完整记录。

如何在合理的时间内将所有传入的 notification 排队,CKRecordID以便我可以一次CKFetchRecordsOperation使用多个 recordID 发出更有效的请求?

4

1 回答 1

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)
    }
  }
}
于 2018-08-06T22:30:29.160 回答