Я получаю до четырех push-уведомлений для каждого события, на которое я подписан. Я просмотрел все, что связано с моими подписками CloudKit и реестром уведомлений, и я убежден, что это проблема Apple. Вместо этого я обратил свое внимание на правильную обработку уведомлений, независимо от того, сколько я получаю. Вот упрощенная версия того, что я делаю:
func recievePrivatePush(_ pushInfo: [String:NSObject], completion: @escaping ()->Void) {
let notification = CKNotification(fromRemoteNotificationDictionary: pushInfo)
let alertBody = notification.alertBody
if let queryNotification = notification as? CKQueryNotification {
let recordID = queryNotification.recordID
guard let body = queryNotification.alertBody else {
return
}
if recordID != nil {
switch body {
case "Notification Type":
let id = queryNotification.recordID
switch queryNotification.queryNotificationReason {
case .recordCreated:
DataCoordinatorInterface.sharedInstance.fetchDataItem(id!.recordName, completion: {
//
})
break
default:
break
}
}
}
}
}
Код получения выглядит примерно так:
func fetchDataItem(_ id: String, completion: @escaping ()-> Void) {
if entityExistsInCoreData(id) {return}
let db = CKContainer.default().privateCloudDatabase
let recordID = CKRecordID(recordName: id)
db.fetch(withRecordID: recordID) { (record, error) in
if let topic = record {
//Here I create and save the object to core data.
}
completion()
}
}
Весь мой код работает, проблема заключается в том, что когда я получаю несколько уведомлений, несколько запросов на выборку запускаются до того, как будет создан первый основной объект данных, что приводит к избыточным объектам основных данных.
Что я хотел бы сделать, так это найти способ добавить запросы на выборку в последовательную очередь, чтобы они обрабатывались по одному. Я могу поместить свои вызовы запросов в последовательную очередь, но обратные вызовы всегда выполняются асинхронно, поэтому несколько запросов на выборку по-прежнему выполняются до того, как будет сохранен первый объект данных.
Я пробовал использовать семафоры и группы отправки с шаблоном, который выглядит следующим образом:
let semaphore = DispatchSemaphore(value: 1)
func recievePrivatePush(_ pushInfo: [String:NSObject], completion: @escaping ()->Void) {
_ = semaphore.wait(timeout: .distantFuture)
let notification = CKNotification(fromRemoteNotificationDictionary: pushInfo)
let alertBody = notification.alertBody
if let queryNotification = notification as? CKQueryNotification {
let recordID = queryNotification.recordID
guard let body = queryNotification.alertBody else {
return
}
if recordID != nil {
switch body {
case "Notification Type":
let id = queryNotification.recordID
switch queryNotification.queryNotificationReason {
case .recordCreated:
DataCoordinatorInterface.sharedInstance.fetchDataItem(id!.recordName, completion: {
semaphore.signal()
})
break
default:
break
}
}
}
}
}
Как только вышеуказанная функция вызывается во второй раз и вызывается semaphore.wait, выполнение первого сетевого запроса приостанавливается, что приводит к зависанию приложения.
Опять же, что я хотел бы сделать, добавляя асинхронные сетевые запросы в очередь, чтобы они выполнялись только по одному за раз, то есть первый сетевой вызов завершался до начала второго запроса.