13

В нашем приложении мы показываем уведомления Notification Center в стиле оповещения.Mac OS X Уведомление NSUserNotificationCenter об увольнении/обратном вызове

Отображение уведомлений работает нормально, а также мы получаем обратный вызов, когда пользователь взаимодействует с уведомлением, либо нажав на уведомление, либо нажав кнопку «Действие».

Однако мы заинтересованы в получении обратного вызова или события, когда пользователь нажимает кнопку «Другие» в уведомлении. Я видел, что MAC OS делает это, когда отображается диалоговое окно, доступное для обновлений.

Обратитесь к этому изображению для разъяснения о OS X обновление имеющейся боевой готовности:

enter image description here

Я искал это через Интернет, а также прошел через документацию this и this центра уведомлений, а также.

Есть ли какой-либо недокументированный API? или какой-либо пользовательский механизм для обнаружения нажмите кнопку «Другие» (закрыть)?

ответ

7

В то время как другая (закрывающая) кнопка явно предназначена для отклонения уведомления, независимо от того, что может указывать его пользовательская подпись, нет элегантного способа получить уведомление, когда пользователь отклонит уведомление, нажав кнопку закрытия.

Что вы можете сделать, однако, это следить за уведомлением по умолчанию для центра уведомлений пользователя по умолчанию . Свойства: до тех пор, пока уведомление еще не было отклонено, массив будет содержать уведомление. Как только уведомление будет отклонено, массив больше не будет содержать его.

Это может быть реализовано в методе делегата NSUserNotificationCenter так:

- (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]; 
         }); 
        }); 
} 

Этот код будет проверять, если уведомление по-прежнему есть каждые 200 миллисекунд. Как только он исчезнет, ​​в основном потоке будет вызываться метод -notificationHandler: method, который является просто методом обратного вызова.

В этом обычном методе -notificationHandler: вы можете проверить, вызван ли метод NSAserNotificationCenter isActivateNotification: delegate для уведомления. Если этого не произошло, пользователь, скорее всего, нажал кнопку закрытия уведомления.

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

+0

Я попробую ваше решение. Однако, что передано свойствоNotifications? Не могли бы вы ссылаться на какую-то документацию? Это недокументировано? Я не нашел через Интернет. – URB

+0

Спасибо за помощь. Теперь я получаю эту идею, и я попробовал ваше решение. Я также понимаю, что это свойство deliverNotifications. Теперь что такое «идентификатор»? Вы имеете в виду какое-то определенное свойство? что мне нужно определить на этом объекте? XCode говорит, что свойство не найдено на объекте NSUserNotification. Извините, но я немного новичок в этом вопросе. – URB

+0

К сожалению, свойство идентификатора является новым в OS X 10.9, и оно не правильно документировано в документах, см. Файл заголовка класса. Короче говоря, это экземпляр NSString, который вы можете использовать для произвольного идентификатора, если хотите. Из файла заголовка: «Этот идентификатор используется для уникальной идентификации уведомления. Уведомление, отправленное с тем же идентификатором, что и существующее уведомление, заменяет это уведомление, а не отображает новое». – Tim

1

В 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: Пожалуйста, обратите внимание, что это способ обнаружить распускать событие, которое может быть запущена в нескольких случаях.

  1. Нажмите otherButton уволить
  2. Нажмите кнопку Clear All в Центре уведомлений

PS 2: Если вы используете deliveryRepeatInterval, скажем, 1 минуту, есть несколько уведомлений в deliveredNotifications массиве, в то время как только один отображается.Увольнение должно инициировать множественные обратные вызовы.

PS 3: При нажатии actionButton будет также вызвать увольнение CallBack

2

В Swift 3

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

Это не является частью NSUserNotificationDelegate, но работает отлично

0

Это помогло мне

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 
    }