Hi.
I'm implementing UNUserNotificationCenter
delegate method:
userNotificationCenter(_:didReceive:withCompletionHandler:)
in MacOS Big-Sur and Catalina, in order to be notified when user dismisses local notifications of my App. (we also handle UNNotificationDefaultActionIdentifier
to focus our UI on the item related to the clicked notification, and we also support 2 custom actionIDs.
It all basically works, and even the UNNotificationDismissActionIdentifier
arrives at the delegate when user dismisses a single notification. (presses the X shaped button on the top-left).
However, when we have a thread of notifications (grouped by some unique threadID, and looks like a stack onscreen) and the user presses the X and then the "Clear all" button to dismiss the whole thread --
the delegate is only called once, for one arbitrary notification in the stack, and there is no way for me to know that a whole thread was dismissed.
-
Am I doing something wrong?
-
Is this a limitation of the delegate protocol?
-
Is this a bug in UNUserNotificationCenter implementation?
-
Is there a workaround, or some trick to know that a whole bunch of notifications were dismissed?
Here's my delegate code (sans irrelevant code...)
// Handle notification back-actions
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response
withCompletionHandler:(nonnull void (^)(void))completionHandler API_AVAILABLE(macos(10.14)) {
NSString *actionId = response.actionIdentifier;
UNNotificationRequest *request = response.notification.request;
NSString *requestId = request.identifier;
NSString *userActionIdentifier = request.content.threadIdentifier;
NSDictionary * myInfo = request.content.userInfo;
if ([actionId isEqualToString:UNNotificationDefaultActionIdentifier]) { // user opened the application from the notification
if ([self.delegate respondsToSelector:@selector(displayThread:forInfo)]) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate displayThread:userActionIdentifier forInfo: myInfo];
});
}
completionHandler();
return;
}
NSString *userReply = nil;
if ([actionId isEqualToString:UNNotificationDismissActionIdentifier]) { // user dismissed the notification
os_log_debug(myLog, "Notification: %{public}@ dismissed", requestId);
}
else { // custom action
NSString *categoryId = response.notification.request.content.categoryIdentifier;
if ([categoryId isEqualToString:OITNotification.copyAction]) {
os_log_debug(myLog, "Notification: %{public}@ dismissed with custom action:%{public}@", requestId, actionId);
}
if ([categoryId isEqualToString:OITPreventionNotification.copyActionWithReply]) {
if ([actionId isEqualToString:@"other"]) {
userReply = [(UNTextInputNotificationResponse*)response userText];
os_log_debug(myLog, "Notification: %{public}@ User custom reply: %{public}@", requestId, userReply);
}
else {
userReply = actionId;
os_log_debug(myLog, "Notification: %{public}@ User Action: %{public}@", requestId, actionId);
}
}
}
if ([self.delegate respondsToSelector:@selector(notification:dismissedWithReply:)]) {
[self.delegate notification:myInfo dismissedWithReply:userReply];
}
[self removeModelIdentifiers:@[response.notification.request.identifier]];
completionHandler();
return;
}
Please ignore the tedious handling of custom actions - my problem is only with "Clear All" thread dismissals. I bring the code just for completeness, in the hopes that someone sees a fault I can't see ---
Thank you very much.