Как поставить в очередь много входящих уведомлений CloudKit

Допустим, я сохранил 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)
  }
}

Но так как каждое из 50 входящих уведомлений является отдельными событиями, эта функция вызывается 50 раз, вызывая множество запросов на получение полных записей с использованием CKRecordIDс, что уведомления дают мне.

Как я могу поставить в очередь все входящие уведомления CKRecordIDв течение разумного периода времени, чтобы я мог сделать более эффективным CKFetchRecordsOperation запрос с более чем одним recordID одновременно?

1 ответ

Я использовал таймер для этого, и он работает довольно хорошо. Обычно я запускаю таймер, когда приходит новое push-уведомление, и сбрасываю его каждый раз, когда приходит дополнительное уведомление. Тем временем я собираю все 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)
    }
  }
}
Другие вопросы по тегам