Mac OS X NSUserNotificationCenter notification get dismiss event/callback

浪尽此生 提交于 2019-11-30 08:32:46

While the other (close) button is clearly meant to dismiss the notification, regardless of what its custom caption may indicate, there is no elegant way to get notified when the user dismisses the notification by clicking on the close button.

What you could do, however, is to monitor the default user notification center's deliveredNotifications property: As long as the notification has not yet been dismissed, the array will contain the notification. Once the notification has been dismissed, the array will not contain it anymore.

This could be implemented in a NSUserNotificationCenter delegate method like this:

- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)notification
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
                   ^{
                       BOOL notificationStillPresent;
                       do {
                           notificationStillPresent = NO;
                           for (NSUserNotification *nox in [[NSUserNotificationCenter defaultUserNotificationCenter] deliveredNotifications]) {
                               if ([nox.identifier isEqualToString:notification.identifier]) notificationStillPresent = YES;
                           }
                           if (notificationStillPresent) [NSThread sleepForTimeInterval:0.20f];
                       } while (notificationStillPresent);
                       dispatch_async(dispatch_get_main_queue(), ^{
                           [self notificationHandlerForNotification:notification];
                       });
                   });
}

This code will check if the notification is still there every 200 milliseconds. Once it is gone, the -notificationHandler: method will be called on the main thread, which is just an arbitrary callback method.

In this custom -notificationHandler: method you could check whether NSUserNotificationCenter's didActivateNotification: delegate method has been called for the notification. If it hasn't, the user most likely clicked on the close button of the notification.

This is not failsafe, though, as the user may also have otherwise dismissed the notification, i.e. without clicking on the close button.

In Swift 3

func userNotificationCenter(_ center: NSUserNotificationCenter, didDismissAlert notification: NSUserNotification) {
        print("dismissed")
    }

This is not part of the NSUserNotificationDelegate but works perfectly

In Swift 2.3:

func userNotificationCenter(center: NSUserNotificationCenter, didDeliverNotification notification: NSUserNotification) {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 
        var notificationStillPresent: Bool
        repeat {
            notificationStillPresent = false
            for nox in NSUserNotificationCenter.defaultUserNotificationCenter().deliveredNotifications {
                if nox.identifier == notification.identifier {
                    notificationStillPresent = true
                    break
                }
            }

            if notificationStillPresent {
                let _ = NSThread.sleepForTimeInterval(0.20)
            }
        } while notificationStillPresent

        dispatch_async(dispatch_get_main_queue()) {
            self.notificationHandlerFor(notification)
        }
    }
}

PS: Please also notice that it is the way to detect the dismiss event, which can be triggered in several cases.

  1. Click the otherButton to dismiss
  2. Click the Clear All button in Notification Center

PS 2: If you are using deliveryRepeatInterval, say 1 minute, there are multiple notifications in deliveredNotifications array, while only one is displayed. The dismissal shall trigger multiple callbacks.

PS 3: Clicking actionButton will also trigger the dismissal callback

This helped me out

func userNotificationCenter(_ center: NSUserNotificationCenter, didActivate notification: NSUserNotification) {
    switch (notification.activationType) {
    case .none:
        print("none CLicked")
        break
    case .actionButtonClicked:
        print("Additional Action Clicked")
        break
    case .contentsClicked:
        print("contents CLicked")
        break
    case .replied:
        print("replied Action Clicked")
        break
    case .additionalActionClicked:
        print("Additional  MENU  Action Clicked")
        break
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!