Excluir uma notificação local específica

Estou desenvolvendo um aplicativo de alarme para iPhone com base em notifications locais.

Ao excluir um alarme, a notificação local relacionada deve ser cancelada. Mas como posso determinar exatamente qual object da matriz de notifications locais deve ser cancelado?

Estou ciente do [[UIApplication sharedApplication] cancelLocalNotification:notification] mas como posso obter essa ‘notificação’ para cancelá-la?

Você pode salvar um valor exclusivo para a chave na userinfo da sua notificação local. Obter todas as notifications locais, percorra a matriz e exclua a notificação específica.

Codifique como segue,

OBJ-C:

 UIApplication *app = [UIApplication sharedApplication]; NSArray *eventArray = [app scheduledLocalNotifications]; for (int i=0; i<[eventArray count]; i++) { UILocalNotification* oneEvent = [eventArray objectAtIndex:i]; NSDictionary *userInfoCurrent = oneEvent.userInfo; NSString *uid=[NSString stringWithFormat:@"%@",[userInfoCurrent valueForKey:@"uid"]]; if ([uid isEqualToString:uidtodelete]) { //Cancelling local notification [app cancelLocalNotification:oneEvent]; break; } } 

RÁPIDO:

 var app:UIApplication = UIApplication.sharedApplication() for oneEvent in app.scheduledLocalNotifications { var notification = oneEvent as UILocalNotification let userInfoCurrent = notification.userInfo! as [String:AnyObject] let uid = userInfoCurrent["uid"]! as String if uid == uidtodelete { //Cancelling local notification app.cancelLocalNotification(notification) break; } } 

UserNotification:

Se você usa o UserNotification (iOS 10+), siga estas etapas:

  1. Ao criar o conteúdo do UserNotification, adicione um identificador exclusivo

  2. Remover notificação pendente específica usando removePendingNotificationRequests (comIdentificadores 🙂

  3. Remover notificação específica enviada usando removeDeliveredNotifications (comIdentificadores 🙂

Para mais informações, UNUserNotificationCenter

Outra opção:

Primeiro de tudo, quando você cria notificação local, você pode armazená-lo em padrões do usuário para uso futuro, object de notificação local não pode ser armazenado diretamente em padrões do usuário, este object precisa ser convertido em object NSData primeiro e depois NSData pode ser armazenado nos User defaults . Abaixo está o código para isso:

 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:localNotif]; [[NSUserDefaults standardUserDefaults] setObject:data forKey:[NSString stringWithFormat:@"%d",indexPath.row]]; 

Depois de ter armazenado e agendado notificação local, no futuro, poderá surgir a necessidade de cancelar qualquer notificação que você tenha criado anteriormente, para que você possa recuperá-la dos padrões do usuário.

 NSData *data= [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"%d",UniqueKey]]; UILocalNotification *localNotif = [NSKeyedUnarchiver unarchiveObjectWithData:data]; NSLog(@"Remove localnotification are %@", localNotif); [[UIApplication sharedApplication] cancelLocalNotification:localNotif]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithFormat:@"%d",UniqueKey]]; 

Espero que isto ajude

Aqui está o que eu faço.

Ao criar sua notificação, faça isso:

  // Create the notification UILocalNotification *notification = [[UILocalNotification alloc] init] ; notification.fireDate = alertDate; notification.timeZone = [NSTimeZone localTimeZone] ; notification.alertAction = NSLocalizedString(@"Start", @"Start"); notification.alertBody = **notificationTitle**; notification.repeatInterval= NSMinuteCalendarUnit; notification.soundName=UILocalNotificationDefaultSoundName; notification.applicationIconBadgeNumber = 1; [[UIApplication sharedApplication] scheduleLocalNotification:notification] ; 

ao tentar excluí-lo, faça o seguinte:

  NSArray *arrayOfLocalNotifications = [[UIApplication sharedApplication] scheduledLocalNotifications] ; for (UILocalNotification *localNotification in arrayOfLocalNotifications) { if ([localNotification.alertBody isEqualToString:savedTitle]) { NSLog(@"the notification this is canceld is %@", localNotification.alertBody); [[UIApplication sharedApplication] cancelLocalNotification:localNotification] ; // delete the notification from the system } } 

Essa solução deve funcionar para várias notifications e você não deve gerenciar matrizes, dictionarys ou padrões do usuário. Você simplesmente usa os dados que já salvou no database de notificação do sistema.

Espero que isso ajude futuros designers e desenvolvedores.

Feliz codificação pessoal! : D

Agendamento e removeNotification no swift:

  static func scheduleNotification(notificationTitle:String, objectId:String) { var localNotification = UILocalNotification() localNotification.fireDate = NSDate(timeIntervalSinceNow: 24*60*60) localNotification.alertBody = notificationTitle localNotification.timeZone = NSTimeZone.defaultTimeZone() localNotification.applicationIconBadgeNumber = 1 //play a sound localNotification.soundName = UILocalNotificationDefaultSoundName; localNotification.alertAction = "View" var infoDict : Dictionary = ["objectId" : objectId] localNotification.userInfo = infoDict; UIApplication.sharedApplication().scheduleLocalNotification(localNotification) } static func removeNotification(objectId:String) { var app:UIApplication = UIApplication.sharedApplication() for event in app.scheduledLocalNotifications { var notification = event as! UILocalNotification var userInfo:Dictionary = notification.userInfo as! Dictionary var infoDict : Dictionary = notification.userInfo as! Dictionary var notifcationObjectId : String = infoDict["objectId"]! if notifcationObjectId == objectId { app.cancelLocalNotification(notification) } } } 

A solução do iMOBDEV funciona perfeitamente para remover uma notificação específica (por exemplo, após a exclusão do alarme), mas é especialmente útil quando você precisa remover seletivamente qualquer notificação que já tenha sido triggersda e ainda esteja no centro de notifications.

Um possível cenário seria: a notificação de um alarme é triggersda, mas o usuário abre o aplicativo sem tocar nessa notificação e programa esse alarme novamente. Se você quiser ter certeza de que apenas uma notificação possa estar no centro de notifications de um determinado item / alarme, é uma boa abordagem. Ele também permite que você não tenha que limpar todas as notifications toda vez que o aplicativo for aberto, caberá melhor no aplicativo.

  • Ao criar uma notificação local, use o NSKeyedArchiver para armazená-lo como Data in UserDefaults . Você pode criar uma chave igual à que você está salvando no dictionary userInfo da notificação. Se estiver associado a um object Core Data, você poderá usar sua propriedade objectID exclusiva.
  • Recupere-o com o NSKeyedUnarchiver . Agora você pode excluí-lo usando o método cancelLocalNotification.
  • Atualize a chave em UserDefaults acordo.

Aqui está uma versão do Swift 3.1 dessa solução (para destinos abaixo do iOS 10):

Loja

 // localNotification is the UILocalNotification you've just set up UIApplication.shared.scheduleLocalNotification(localNotification) let notificationData = NSKeyedArchiver.archivedData(withRootObject: localNotification) UserDefaults.standard.set(notificationData, forKey: "someKeyChosenByYou") 

Recuperar e excluir

 let userDefaults = UserDefaults.standard if let existingNotificationData = userDefaults.object(forKey: "someKeyChosenByYou") as? Data, let existingNotification = NSKeyedUnarchiver.unarchiveObject(with: existingNotificationData) as? UILocalNotification { // Cancel notification if scheduled, delete it from notification center if already delivered UIApplication.shared.cancelLocalNotification(existingNotification) // Clean up userDefaults.removeObject(forKey: "someKeyChosenByYou") } 

Versão rápida, se necessário:

 func cancelLocalNotification(UNIQUE_ID: String){ var notifyCancel = UILocalNotification() var notifyArray = UIApplication.sharedApplication().scheduledLocalNotifications for notifyCancel in notifyArray as! [UILocalNotification]{ let info: [String: String] = notifyCancel.userInfo as! [String: String] if info[uniqueId] == uniqueId{ UIApplication.sharedApplication().cancelLocalNotification(notifyCancel) }else{ println("No Local Notification Found!") } } } 

O object UILocalNotification que você passa para cancelLocalNotification: corresponderá a qualquer object UILocalNotification existente com propriedades correspondentes.

Assim:

 UILocalNotification *notification = [[UILocalNotification alloc] init]; notification.alertBody = @"foo"; [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; 

apresentará uma notificação local que pode ser cancelada posteriormente com:

 UILocalNotification *notification = [[UILocalNotification alloc] init]; notification.alertBody = @"foo"; [[UIApplication sharedApplication] cancelLocalNotification:notification]; 

Eu uso essa function no Swift 2.0:

  static func DeleteNotificationByUUID(uidToDelete: String) -> Bool { let app:UIApplication = UIApplication.sharedApplication() // loop on all the current schedualed notifications for schedualedNotif in app.scheduledLocalNotifications! { let notification = schedualedNotif as UILocalNotification let urrentUi = notification.userInfo! as! [String:AnyObject] let currentUid = urrentUi["uid"]! as! String if currentUid == uidToDelete { app.cancelLocalNotification(notification) return true } } return false } 

Inspirado da resposta do @ KingofBliss

Você pode manter uma string com o identificador de categoria ao agendar a notificação assim

  localNotification.category = NotificationHelper.categoryIdentifier 

e procurá-lo e cancelar quando necessário, assim

 let app = UIApplication.sharedApplication() for notification in app.scheduledLocalNotifications! { if let cat = notification.category{ if cat==NotificationHelper.categoryIdentifier { app.cancelLocalNotification(notification) break } } } 

Para Lembretes Repetidos (Por exemplo, você quer que seu alarme seja triggersdo no Domingo, Sáb e Qua às 4 PM, Então você tem que fazer 3 alarmes e setar repeatInterval para NSWeekCalendarUnit).

Para fazer um lembrete apenas uma vez:

 UILocalNotification *aNotification = [[UILocalNotification alloc] init]; aNotification.timeZone = [NSTimeZone defaultTimeZone]; aNotification.alertBody = _reminderTitle.text; aNotification.alertAction = @"Show me!"; aNotification.soundName = UILocalNotificationDefaultSoundName; aNotification.applicationIconBadgeNumber += 1; NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; NSDateComponents *componentsForFireDate = [calendar components:(NSYearCalendarUnit | NSWeekCalendarUnit| NSHourCalendarUnit | NSMinuteCalendarUnit| NSSecondCalendarUnit | NSWeekdayCalendarUnit) fromDate: _reminderDate]; [componentsForFireDate setHour: [componentsForFireDate hour]] ; //for fixing 8PM hour [componentsForFireDate setMinute:[componentsForFireDate minute]]; [componentsForFireDate setSecond:0] ; NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate]; aNotification.fireDate = fireDateOfNotification; NSDictionary *infoDict = [NSDictionary dictionaryWithObject:_reminderTitle.text forKey:kRemindMeNotificationDataKey]; aNotification.userInfo = infoDict; [[UIApplication sharedApplication] scheduleLocalNotification:aNotification]; 

Para fazer lembrete repetido:

 for (int i = 0 ; i  

Para filtragem você matriz para exibi-lo.

 -(void)filterNotficationsArray:(NSMutableArray*) notificationArray{ _dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication] scheduledLocalNotifications]]; NSMutableArray *uniqueArray = [NSMutableArray array]; NSMutableSet *names = [NSMutableSet set]; for (int i = 0 ; i<_dataArray.count; i++) { UILocalNotification *localNotification = [_dataArray objectAtIndex:i]; NSString * infoDict = [localNotification.userInfo objectForKey:@"kRemindMeNotificationDataKey"]; if (![names containsObject:infoDict]) { [uniqueArray addObject:localNotification]; [names addObject:infoDict]; } } _dataArray = uniqueArray; } 

Para remover o lembrete, foi apenas uma vez ou repetido:

 - (void) removereminder:(UILocalNotification*)notification { _dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication]scheduledLocalNotifications]]; NSString * idToDelete = [notification.userInfo objectForKey:@"kRemindMeNotificationDataKey"]; for (int i = 0 ; i<_dataArray.count; i++) { UILocalNotification *currentLocalNotification = [_dataArray objectAtIndex:i]; NSString * notificationId = [currentLocalNotification.userInfo objectForKey:@"kRemindMeNotificationDataKey"]; if ([notificationId isEqualToString:idToDelete]) [[UIApplication sharedApplication]cancelLocalNotification:currentLocalNotification]; } _dataArray = [[NSMutableArray alloc]initWithArray:[[UIApplication sharedApplication]scheduledLocalNotifications]]; [self filterNotficationsArray:_dataArray]; [_remindersTV reloadData]; } 

Eu expandi um pouco a resposta de KingofBliss, escrevi isso um pouco mais como um Swift2, removi alguns códigos desnecessários e adicionei alguns protetores.

Para começar, ao criar a notificação, você precisa definir o uid (ou qualquer propriedade personalizada realmente) da userInfo da notificação:

 notification.userInfo = ["uid": uniqueid] 

Então, ao excluí-lo, você pode fazer:

 guard let app: UIApplication = UIApplication.sharedApplication(), let notifications = app.scheduledLocalNotifications else { return } for notification in notifications { if let userInfo = notification.userInfo, let uid: String = userInfo["uid"] as? String where uid == uidtodelete { app.cancelLocalNotification(notification) print("Deleted local notification for '\(uidtodelete)'") } } 

3-estilo rápido:

 final private func cancelLocalNotificationsIfIOS9(){ //UIApplication.shared.cancelAllLocalNotifications() let app = UIApplication.shared guard let notifs = app.scheduledLocalNotifications else{ return } for oneEvent in notifs { let notification = oneEvent as UILocalNotification if let userInfoCurrent = notification.userInfo as? [String:AnyObject], let uid = userInfoCurrent["uid"] as? String{ if uid == uidtodelete { //Cancelling local notification app.cancelLocalNotification(notification) break; } } } 

}

para iOS 10 use:

  let center = UNUserNotificationCenter.current() center.removePendingNotificationRequests(withIdentifiers: [uidtodelete]) 

Solução Swift 4:

 UNUserNotificationCenter.current().getPendingNotificationRequests { (requests) in for request in requests{ if request.content.categoryIdentifier == "identifier"{ UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["identifier"]) } } }