Почему уведомления не удаляются с помощью removeDeliveredNotifications?

До недавнего времени (я полагаю, до выпуска iOS 12) удаление удаленных push-уведомлений из Центра уведомлений работало должным образом с использованием removeDeliveredNotifications.

Внезапно, без изменения кода в расширении службы уведомлений, уведомления больше не удаляются.

override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {

    self.contentHandler = contentHandler
    self.content = request.content.mutableCopy() as? UNMutableNotificationContent

    guard let content = content else {
        contentHandler(request.content)
        return
    }

    UNUserNotificationCenter.current().getDeliveredNotifications { notifications in
        let matchingNotifications = notifications.filter({ $0.request.content.threadIdentifier == "myThread" && $0.request.content.categoryIdentifier == "myCategory" })
        UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: matchingNotifications.map({ $0.request.identifier }))
        contentHandler(content)
    }
}

Функция просто завершается без удаления уведомления. При отладке на реальном устройстве он показывает, что matchingNotifications содержит уведомления и правильно указаны идентификаторы уведомлений, которые необходимо удалить.

Для тестирования вызов removeAllDeliveredNotifications() работает и удаляет все уведомления.

Вышеупомянутая функция вызывается в override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void)

В чем проблема?


comment
Привет, @Manuel, ты нашел какое-нибудь решение этой проблемы?   -  person Skaal    schedule 10.01.2019
comment
@Skaal Нет, это все еще проблема. Напишите здесь, если найдете решение.   -  person Manuel    schedule 11.01.2019
comment
Можете ли вы опубликовать свою полную didReceive реализацию? Я считаю, что это связано с когда вы вызываете contentHandler завершение.   -  person Kymer    schedule 26.01.2019
comment
Обработчик завершения @Kymer вызывается после удаления уведомлений, см. Обновленный код. Опять же, он всегда работал нормально в течение нескольких месяцев, пока внезапно не перестал работать.   -  person Manuel    schedule 26.01.2019
comment
Из того, что я прочитал, это поведение действительно изменилось с момента выхода iOS 12. Метод удаления возвращается немедленно, но выполняется асинхронно, вызывая contentHandler выгружает / уничтожает ваше расширение (я полагаю), что может остановить асинхронное удаление. Можете ли вы попробовать отложить звонок contentHandler в целях тестирования? (задержка на пару секунд например)   -  person Kymer    schedule 26.01.2019
comment
@Kymer Я протестирую это и опубликую обновление. У вас есть ссылка на это новое поведение?   -  person Manuel    schedule 26.01.2019
comment
@Manuel Официально это не задокументировано, просто видел, как некоторые люди в Интернете испытывали такое же поведение, начиная с iOS 12. (комментарий к это сообщение в блоге, например, Guardian)   -  person Kymer    schedule 26.01.2019
comment
@Kymer, кто-нибудь нашел решение? Проблема только в iOS 12+. Я буду очень признателен   -  person Vlad Pulichev    schedule 06.05.2019


Ответы (1)


Я попробовал предложение @Kymer и подтвердил, что вызов contentHandler после некоторого ожидания (например, 3 секунд) решил проблему для меня. , например

// UNUserNotificationCenter *notificationCenter
// NSArray(NSString *) *matchingIdentifiers;
// UNNotificationContent *content;
if (matchingIdentifiers.count > 0) {
    NSLog(@"NotificationService: Matching notification identifiers to remove: %@.", matchingIdentifiers);               
    [notificationCenter removeDeliveredNotificationsWithIdentifiers:matchingIdentifiers];

    // Note: dispatch delay is in nanoseconds... :(
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3000000000), dispatch_get_main_queue(), ^{
        NSLog(@"Replacing content after 3 seconds.");
        self.contentHandler(content);
    });
}

Я думаю, это означает, что это проблема времени, когда iOS агрессивно замораживает процесс после вызова contentHandler и удаляет все ожидающие запросы на удаление в notificationCenter

РЕДАКТИРОВАТЬ: хотя вопрос не в том, как с этим бороться, раздел комментариев вызвал опасения по поводу произвольной задержки по времени. В моем тестировании было достаточно разместить обратный вызов в другом цикле, например

dispatch_async(dispatch_get_main_queue(), ^{
    contentHandler(content);
});
person Simon Bocanegra Thiel    schedule 18.06.2019
comment
Если произвольная задержка - единственное решение, значит, это ошибка. - person Manuel; 19.06.2019
comment
Этот обходной путь сработал. Я не пытался найти минимально необходимое время задержки, но опытным путем достаточно использовать 500 мс в качестве задержки. Боковое примечание: задержка может иметь видимый эффект для пользователя в центре уведомлений, потому что уведомления удаляются сразу же при вызове removeDeliveredNotifications, но любой код, который приходит дальше, выполняется после задержки. - person Manuel; 30.06.2019
comment
Кстати: вам не нужно добавлять произвольную задержку отправки. Я проверил, что он работает, отправив обратный вызов self.contentHandler (content) в другом цикле, например. следующий опрос в основной очереди dispatch_async(dispatch_get_main_queue(), ^{ contentHandler(content); }); (извините, не могу понять блок кода в mini-Markdown) - person Simon Bocanegra Thiel; 28.08.2019
comment
@SimonBocanegraThiel, который никогда не работал у меня, вместо этого я использовал задержку 0,1. - person Lucas van Dongen; 14.05.2020