Я получаю до четырех push-уведомлений для каждого события, на которое я подписан. Я прошел через все, что связано с моими подписками CloudKit и реестром уведомлений, и я убежден, что это проблема Apple. Вместо этого я обратил внимание на правильную обработку уведомлений независимо от того, сколько я получаю. Вот упрощенная версия того, что я делаю:Создайте очередную очередь для сетевых вызовов, сгенерированных push-уведомлениями
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 называется, выполнение первой пауза в сети, что приводит к замороженному приложению.
Опять же, что бы я хотел сделать, добавляя асинхронные сетевые запросы в очередь, чтобы они делались только по одному, то есть первый сетевой вызов завершается до запуска второго запроса.
Carl, Unsure, если я четко понял проблему, но здесь есть альтернативный подход к работе с несколькими [дублирующимися] уведомлениями. Это очень просто, просто используйте словарь для сохранения уведомлений по мере их поступления, чтобы вы могли легко распознать дубликаты. Таким образом, даже если вы получите второе или третье или более уведомление об одном и том же событии, это не имеет значения. Вы просто проверяете свой словарь и выбрасываете дубликат. – user3069232
Проблема заключается в том, что уведомления поступают почти одновременно и обрабатываются делегатом приложения параллельно. Я получу несколько ложных срабатываний, прежде чем придет время добавить пару значений ключа в словарь и проверить на это. – CarlNathan