Up until recently (I believe prior to iOS 12 release), removing remote push notifications from the Notification Center worked as expected using removeDeliveredNotifications
.
Suddenly, without any code change in the Notification Service Extension, notifications are not removed anymore.
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)
}
}
The function just completes without removing the notification. When debugging on a real device, it shows that matchingNotifications
contains notifications and the notification IDs to remove are correctly provided.
For testing, calling removeAllDeliveredNotifications()
works and removes all notifications.
The function above is called in override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void)
What is the problem here?
I tried the suggestion by @Kymer and verified that calling contentHandler
after waiting some time (e.g. 3 seconds) resolved the issue for me, e.g.
// 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);
});
}
So I think this means it's a timing issue, with iOS freezing the process aggressively after the contentHandler
is invoked, and removing any pending removal requests in the notificationCenter
EDIT: Although the question wasn't about how to deal with it, the comment section brought concerns about an arbitrary time delay. In my testing, posting the callback on another loop sufficed, e.g.
dispatch_async(dispatch_get_main_queue(), ^{
contentHandler(content);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With