Отменить UILocalNotification

У меня проблема с моим UILocalNotification.

Я планирую уведомление с помощью своего метода.

- (void) sendNewNoteLocalReminder:(NSDate *)date  alrt:(NSString *)title
{
    // some code ...
    UILocalNotification *localNotif = [[UILocalNotification alloc] init]; 

    if (localNotif == nil)  
        return;

    localNotif.fireDate = itemDate; 
    localNotif.timeZone = [NSTimeZone defaultTimeZone];
    localNotif.alertAction = NSLocalizedString(@"View Details", nil); 
    localNotif.alertBody = title;
    localNotif.soundName = UILocalNotificationDefaultSoundName; 
    localNotif.applicationIconBadgeNumber = 0;

    NSDictionary *infoDict = [NSDictionary dictionaryWithObject:stringID forKey:@"id"]; 
    localNotif.userInfo = infoDict; 

    [[UIApplication sharedApplication] scheduleLocalNotification:localNotif]; 
    [localNotif release];
}

Он работает нормально, и я правильно получаю уведомление. Проблема в том, когда я должен отменить уведомление. Я использую этот метод.

- (void) deleteNewNoteLocalReminder:(NSString*) reminderID noteIDe:(NSInteger)noteIDE
{
    [[UIApplication sharedApplication] cancelLocalNotification:(UILocalNotification *)notification ????  
}

Я не уверен, что делать здесь, но мои вопросы:

Как узнать, какой объект UILocalNotification следует удалить?
Есть ли способ составить список всех уведомлений?

Единственное, что у меня есть, это идентификатор напоминания, которое я должен удалить.
Я думал о том, чтобы сохранить объект UILocalNotification в моем объекте «Заметка» и получить его таким образом, а при сохранении в моей базе данных SQLite сериализовать объект и так далее... есть способ поумнее?


person f0rz    schedule 01.07.2010    source источник


Ответы (10)


Свифт 5:

UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: arrayContainingIdentifiers)
person Mostafa ElShazly    schedule 19.05.2019
comment
На случай, если какой-либо разработчик Xamarin будет искать ответ. Этот работал аккуратно для меня. UNUserNotificationCenter.Current.RemovePendingNotificationRequests(new string[] { NotificationId }); - person Sergey Ivanov; 18.02.2021

Мое решение — использовать словарь UILocalNotification userInfo. На самом деле я генерирую уникальный идентификатор для каждого из моих уведомлений (конечно, этот ID я могу получить позже), а затем, когда я захочу чтобы отменить уведомление, связанное с данным ID, я просто просканирую все доступные уведомления, используя массив:

[[UIApplication sharedApplication] scheduledLocalNotifications]

а затем я пытаюсь сопоставить уведомления, исследуя ID. Например.:


NSString *myIDToCancel = @"some_id_to_cancel";
UILocalNotification *notificationToCancel=nil;
for(UILocalNotification *aNotif in [[UIApplication sharedApplication] scheduledLocalNotifications]) {
  if([[aNotif.userInfo objectForKey:@"ID"] isEqualToString:myIDToCancel]) {
     notificationToCancel=aNotif;
     break;
  }
}
if(notificationToCancel) [[UIApplication sharedApplication] cancelLocalNotification:notificationToCancel];

Я не знаю, лучше ли этот подход по сравнению с архивированием/разархивированием, однако он работает и ограничивает данные для сохранения только идентификатором.

Редактировать: отсутствовала скоба

person viggio24    schedule 02.02.2011
comment
Я попробовал ваш метод и не работал для меня. не могли бы вы сказать мне, что не так? stackoverflow.com/questions/9139586/ - person Farini; 04.02.2012
comment
Вы не используете мой метод в своем решении. Мое решение передает идентификатор, а вы используете весь объект. Из вашего кода кажется, что существует раннее освобождение объекта уведомления, и поэтому нераспознанный селектор (это обычно происходит, когда старое местоположение объекта было повторно использовано другим типом объекта). Попробуйте получить имя класса объекта непосредственно перед отправкой сообщения cancelNotification, чтобы покопаться в нем, это может помочь при отладке. Кроме того, когда вы назначаете уведомление, используйте self.theNotification = ... вместо theNotificaiton = ... - person viggio24; 04.02.2012
comment
Большое спасибо ! Вы на самом деле вдохновили меня добавить кнопку в каждую ячейку, где я могу: отменитьLocalNotification atindex [тег отправителя], и это работает намного лучше, чем создание uialertview. Как вы сказали, имя объекта теперь прямо перед отменой, и оно работает просто отлично! - person Farini; 05.02.2012
comment
Да, я видел ваш ответ на ваш вопрос. Я согласен с вами в том, что добавление кнопки, а затем отмена уведомления в ее селекторе идеально подходит для вашего конкретного случая. - person viggio24; 05.02.2012
comment
При использовании CoreDate мне показалось полезным использовать уникальный идентификатор управляемого объекта: NSManagedObjectID *moID = [managedObject objectID];. Поскольку CoreData присваивает постоянный идентификатор только после сохранения, вы можете использовать: BOOL isTemporary = [[managedObject objectID] isTemporaryID]; - person d.ennis; 05.04.2012
comment
Обратите внимание, что это работает только для запланированных уведомлений; вы не можете отменить уведомление, представленное через presentLocalNotificationNow:. - person Nick Farina; 12.06.2014
comment
Любое исправление для уведомлений iOS 10? - person Danpe; 21.09.2016
comment
В iOS 10 UILocalNotification устарел. Вам нужно использовать класс UNNotificationRequest, который поддерживает поле идентификатора. Этот идентификатор можно кэшировать (или получить с помощью метода getPendingNotificationRequestsWithCompletionHandler:), а уведомления можно выборочно удалить с помощью метода removePendingNotificationRequestsWithIdentifiers:. - person viggio24; 22.09.2016

Вы можете получить список всех запланированных уведомлений по адресу scheduledLocalNotifications или вы можете отменить их все:

  [[UIApplication sharedApplication] cancelAllLocalNotifications];
person progrmr    schedule 01.07.2010
comment
Я знаю об CancelAllLocalNotifications, но я просто хочу отменить конкретный. ScheduledLocalNotifications, возможно, сделают свое дело.... Я попробую. - person f0rz; 01.07.2010

Мое решение состоит в том, чтобы заархивировать объект UILocalNotification, который вы запланировали с помощью NSKeyedArchiver, и сохранить его где-нибудь (предпочтительно в plist). А затем, когда вы хотите отменить уведомление, найдите в plist правильные данные и используйте NSKeyedUnarchiver для разархивирования. Код довольно прост:

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:notice];

и

UILocalNotification *notice = [NSKeyedUnarchiver unarchiveObjectWithData:data];
person hiepnd    schedule 26.07.2010
comment
Вы также можете сериализовать NSData из archievedDataWithRootObject с кодировкой Base64, а затем сохранить в объект JSON, который у вас уже есть. - person Rafael Sanches; 28.04.2012
comment
@RafaelSanches извините за некрофилию. Но в чем преимущество использования объекта JSON, если целью является сохранение/извлечение uilocalnotification для последующего удаления? - person iamdavidlam; 04.05.2015

Мое решение - вы, когда вы создаете UILocalNotification, в то время вы создаете один NSMutableDictionary и сохраняете это уведомление как значение для ключа в качестве своего идентификатора и помещаете это NSMutableDictionay в свой NSUserDefaults

Поэтому, когда вы хотите отменить какое-либо конкретное локальное уведомление в это время, вы пишете [dictionary valueforkey @"KEY"], где в качестве ключа вы передаете свой идентификатор, чтобы получить это конкретное локальное уведомление и передать его в

 [[UIApplication sharedApplication] scheduleLocalNotification:localNotif]; 
person Mahek    schedule 30.07.2010

В Swift вы сначала добавляете dict к уведомлениям userInfo:

let dict:NSDictionary = ["ID" : "someString"]
notification.userInfo = dict as! [String : String]

Затем вы хотите получить массив существующих уведомлений (2) и перебирать каждое из них (3), пока не найдете то, что ищете. Как только вы найдете его, отмените его (4).

// 1. Pass in the string you want to cancel
func cancelLocalNotification(uniqueId: String){

    // 2. Create an array of notifications, ensuring to use `if let` so it fails gracefully
    if let notifyArray = UIApplication.sharedApplication().scheduledLocalNotifications {

        // 3. For each notification in the array ...
        for notif in notifyArray as [UILocalNotification] {
            // ... try to cast the notification to the dictionary object
            if let info = notif.userInfo as? [String: String] {

                // 4. If the dictionary object ID is equal to the string you passed in ...
                if info["ID"] == uniqueId {
                    // ... cancel the current notification
                    UIApplication.sharedApplication().cancelLocalNotification(notif)
                }
            }
        }
    }
}
person bwash70    schedule 06.01.2016
comment
Примечание. UIApplication.sharedApplication() теперь называется UIApplication.shared. - person Andrea Leganza; 22.10.2017

Версия Swift:

UIApplication.sharedApplication().cancelAllLocalNotifications()
person fatihyildizhan    schedule 14.02.2016

Версия Swift для отмены конкретного «Локального уведомления» с использованием информации о пользователе.:

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!")
            }
        }
    }
person Sohil R. Memon    schedule 25.06.2015

Мое решение состоит в том, чтобы удалить все запланированные уведомления об этих методах.

-applicationDidFinishLaunchingWithOptions: 
- (void)applicationDidBecomeActive:(UIApplication *)application;
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;

с участием

[[UIApplication sharedApplication] cancelAllLocalNotifications];

Вы по-прежнему можете получить доступ к объекту LocalNotification, активировавшему ваше приложение, с помощью.

    UILocalNotification *localNotif = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey];

Затем я переназначаю новые уведомления на

- (void)applicationDidEnterBackground:(UIApplication *)application;

Это позволяет избежать учета всех уведомлений. Я также отправляю некоторую контекстную информацию в словарь userInfo. Затем это помогает перейти в нужное место в приложении.

person orkoden    schedule 15.06.2012

Спасибо @viggio24 за хороший ответ, это быстрая версия

var notifyCancel = UILocalNotification()
var notifyArray=UIApplication.sharedApplication().scheduledLocalNotifications
var i = 0
while(i<notifyArray.count){
    if let notify = notifyArray[i] as? UILocalNotification{
        if let info = notify.userInfo as? Dictionary<String,String> {
            if let s = info["name"] {
                if(name==s){//name is the the one you want cancel
                    notifyCancel = notify
                    break
                }
            }
        }
    }
i++
}
person 王怡飞    schedule 09.03.2015
comment
Не нужно время, и если позволить уведомить, просто сделайте его коротким с for notify in notifyArray as [UILocalNotification] { if let info = notifier.userInfo as? Dictionary<String,String> {...}} - person Nitro.de; 01.04.2015