Je développe une application d'alarme iPhone basée sur les notifications locales.
Lors de la suppression d'une alarme, la notification locale associée doit être annulée. Mais comment puis-je déterminer exactement quel objet du tableau de notifications locales doit être annulé?
Je suis conscient de [[UIApplication sharedApplication] cancelLocalNotification:notification]
méthode, mais comment puis-je obtenir cette "notification" pour l'annuler?
Vous pouvez enregistrer une valeur unique pour la clé dans les informations utilisateur de votre notification locale. Obtenez toutes les notifications locales, parcourez le tableau et supprimez la notification en question.
Code comme suit,
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;
}
}
Rapide:
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:
Si vous utilisez serNotification (iOS 10+), procédez comme suit:
Lors de la création du contenu UserNotification, ajoutez un nom unique identifiant
Supprimer une notification en attente spécifique à l'aide de removePendingNotificationRequests (withIdentifiers:)
Supprimer une notification remise spécifique à l'aide de removeDeliveredNotifications (withIdentifiers:)
Pour plus d'informations, NUserNotificationCenter
Autre option:
Tout d'abord, lorsque vous créez une notification locale, vous pouvez la stocker dans les valeurs par défaut de l'utilisateur pour une utilisation ultérieure. L'objet de notification local ne peut pas être stocké directement dans les valeurs par défaut de l'utilisateur. Cet objet doit d'abord être converti en objet NSData, puis NSData
peut être stocké dans User defaults
. Voici le code pour cela:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:localNotif];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:[NSString stringWithFormat:@"%d",indexPath.row]];
Une fois que vous avez stocké et planifié la notification locale, vous devrez peut-être annuler toute notification créée précédemment, afin de pouvoir la récupérer à partir des paramètres par défaut de l'utilisateur.
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]];
J'espère que cela t'aides
Voici ce que je fais.
Lorsque vous créez votre notification, procédez comme suit:
// 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] ;
lorsque vous essayez de le supprimer, procédez comme suit:
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
}
}
Cette solution devrait fonctionner pour plusieurs notifications et ne pas gérer de tableaux, de dictionnaires ou de valeurs utilisateur par défaut. Vous utilisez simplement les données que vous avez déjà enregistrées dans la base de notification des systèmes.
J'espère que cela aidera les futurs concepteurs et développeurs.
Bonne codage les gars! :RÉ
Planification et suppression de la notification dans 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<String,String!> = ["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<String,String!> = notification.userInfo as! Dictionary<String,String!>
var infoDict : Dictionary = notification.userInfo as! Dictionary<String,String!>
var notifcationObjectId : String = infoDict["objectId"]!
if notifcationObjectId == objectId {
app.cancelLocalNotification(notification)
}
}
}
iMOBDEV's solution fonctionne parfaitement pour supprimer une notification spécifique (par exemple, après la suppression de l'alarme), mais il est particulièrement utile lorsque vous devez supprimer de manière sélective toute notification qui a déjà été déclenchée et se trouve toujours sur le centre de notification.
Un scénario possible serait: la notification pour une alarme se déclenche, mais l'utilisateur ouvre l'application sans appuyer sur cette notification et programme à nouveau cette alarme. Si vous voulez vous assurer qu'une seule notification peut figurer dans le centre de notification pour un élément/une alarme donné, c'est une bonne approche. Il vous permet également de ne pas effacer toutes les notifications chaque fois que l'application est ouverte, si cela convient mieux à l'application.
NSKeyedArchiver
pour la stocker sous le nom Data
dans UserDefaults
. Vous pouvez créer une clé égale à celle que vous enregistrez dans le dictionnaire userInfo de la notification. S'il est associé à un objet Core Data, vous pouvez utiliser sa propriété unique objectID.NSKeyedUnarchiver
. Vous pouvez maintenant le supprimer à l'aide de la méthode cancelLocalNotification.UserDefaults
en conséquence.Voici une version Swift 3.1 de cette solution (pour les cibles inférieures à iOS 10):
Stocker
// 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")
Récupérer et supprimer
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")
}
Version Swift, si besoin:
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!")
}
}
}
solution Swift 4:
UNUserNotificationCenter.current().getPendingNotificationRequests { (requests) in
for request in requests {
if request.identifier == "identifier" {
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["identifier"])
}
}
}
L'objet UILocalNotification que vous transmettez à cancelLocalNotification:
fera correspondre tout objet UILocalNotification existant avec les propriétés correspondantes.
Alors:
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = @"foo";
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
présentera une notification locale qui pourra être annulée ultérieurement avec:
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = @"foo";
[[UIApplication sharedApplication] cancelLocalNotification:notification];
Vous pouvez conserver une chaîne avec l'identificateur de catégorie lors de la planification de la notification,
localNotification.category = NotificationHelper.categoryIdentifier
et rechercher et annuler si nécessaire comme si
let app = UIApplication.sharedApplication()
for notification in app.scheduledLocalNotifications! {
if let cat = notification.category{
if cat==NotificationHelper.categoryIdentifier {
app.cancelLocalNotification(notification)
break
}
}
}
J'utilise cette fonction dans 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
}
Inspiré de la réponse de @ KingofBliss
Swift 3-style:
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;
}
}
}
}
pour iOS 10 utiliser:
let center = UNUserNotificationCenter.current()
center.removePendingNotificationRequests(withIdentifiers: [uidtodelete])
Pour les rappels répétés (par exemple, vous voulez que votre alarme sonne le dimanche, le samedi et le mercredi à 4 PM, puis vous devez créer 3 alarmes et définir REINTERTERVAL sur NSWeekCalendarUnit).
Pour faire une fois seulement rappel:
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];
Pour faire des rappels répétés:
for (int i = 0 ; i <reminderDaysArr.count; i++)
{
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 setWeekday: [[reminderDaysArr objectAtIndex:i]integerValue]];
[componentsForFireDate setHour: [componentsForFireDate hour]] ; // Setup Your Own Time.
[componentsForFireDate setMinute:[componentsForFireDate minute]];
[componentsForFireDate setSecond:0] ;
NSDate *fireDateOfNotification = [calendar dateFromComponents: componentsForFireDate];
aNotification.fireDate = fireDateOfNotification;
aNotification.repeatInterval = NSWeekCalendarUnit;
NSDictionary *infoDict = [NSDictionary dictionaryWithObject:_reminderTitle.text forKey:kRemindMeNotificationDataKey];
aNotification.userInfo = infoDict;
[[UIApplication sharedApplication] scheduleLocalNotification:aNotification];
}
}
Pour Filtrer votre tableau pour l'afficher.
-(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;
}
Pour supprimer le rappel même si c'était une fois seulement ou répété:
- (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];
}
J'ai développé un peu la réponse de KingofBliss, écrit ceci un peu plus comme Swift2, enlevé du code inutile et ajouté quelques gardes du crash.
Pour commencer, lors de la création de la notification, vous devez vous assurer que vous définissez bien l'ID (ou toute propriété personnalisée) de la notification userInfo
:
notification.userInfo = ["uid": uniqueid]
Ensuite, lorsque vous le supprimez, vous pouvez faire:
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)'")
}
}