Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are notifications not removed with removeDeliveredNotifications?

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?

like image 419
Manuel Avatar asked Dec 09 '18 22:12

Manuel


1 Answers

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);
});
like image 184
Simon Bocanegra Thiel Avatar answered Oct 19 '22 16:10

Simon Bocanegra Thiel