Belirli bir yerel bildirimi silin


92

Yerel bildirimlere dayalı bir iPhone alarm uygulaması geliştiriyorum.

Bir alarmın silinmesi üzerine, ilgili yerel bildirimin iptal edilmesi gerekir. Ancak yerel bildirimler dizisinden tam olarak hangi nesnenin iptal edileceğini nasıl belirleyebilirim?

[[UIApplication sharedApplication] cancelLocalNotification:notification]Yöntemin farkındayım ancak iptal etmek için bu 'bildirimi' nasıl alabilirim?

Yanıtlar:


218

Yerel bildiriminizin kullanıcı bilgisindeki anahtar için benzersiz bir değer kaydedebilirsiniz. Tüm yerel bildirimleri alın, dizide döngü yapın ve belirli bildirimi silin.

Aşağıdaki gibi kodlayın,

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;
    }
}

SWIFT:

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:

UserNotification (iOS 10+) kullanıyorsanız, şu adımları uygulamanız yeterlidir :

  1. UserNotification içeriğini oluştururken benzersiz bir tanımlayıcı ekleyin

  2. RemovePendingNotificationRequests (withIdentifiers :) kullanarak belirli bekleyen bildirimleri kaldırın

  3. RemoveDeliveredNotifications (withIdentifiers :) kullanarak belirli teslim edilen bildirimleri kaldırın

Daha fazla bilgi için UNUserNotificationCenter


@ kingofBliss, lütfen bana orada "uidtodelete" de vermemi söyleyebilir misiniz? çünkü benim durumumda beyan edilmemiştir.
ishhhh

@ishhh itsjust bir strig değeri .. Eğer silme olmasını beyan ve sıvısındaki bir değerle başlatılamadığı gerekir
KingofBliss

kingofBliss @, uid her zaman beni this.Please yardım kurtulmak için nasıl NSLog.dont konw içinde null adlı gösteriyor
ishhhh

@ishhh, yerel bildirim oluştururken kullanıcı bilgisi sözlüğünde uid için herhangi bir değer depoladınız mı? Sanırım bunu kaçırdın.
KingofBliss

@kingofBliss, "uid" kendi değişkeninizin adıdır, "bildirim NSDictionarykimliği " gibi herhangi bir anlamlı adı kullanabilir ve bunu. ile ilgili varlığın kimliğinin değeriyle birlikte saklayabilirsiniz UILocalNotification. Ardından, özel verilerinizle birlikte notification.userInfo özelliğini sözlüğe ayarlayın. Artık bildirimleri aldığınızda, bunları bu özel kimlik veya ihtiyaç duyabileceğiniz başka herhangi bir şeyle ayırt edebilirsiniz.
IgniteCoders

23

Diğer seçenek:

Her şeyden önce, yerel bildirim oluşturduğunuzda, ileride kullanmak üzere kullanıcı varsayılanlarında saklayabilirsiniz, Yerel bildirim nesnesi doğrudan kullanıcı varsayılanlarında saklanamaz, Bu nesnenin önce NSData nesnesine dönüştürülmesi ve ardından şuraya NSDatadepolanması gerekir. User defaults. Bunun için kod aşağıdadır:

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

Yerel bildirimi kaydettikten ve programladıktan sonra, gelecekte daha önce oluşturduğunuz herhangi bir bildirimi iptal etmeniz gerekebilir, Böylece bunu Kullanıcı varsayılanlarından alabilirsiniz.

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]];

Bu yardımcı olur umarım


Teşekkürler, ilk olarak uyguladım ama cevabınız da doğru, bunu dikkate alacağım, hangisinin daha verimli olduğunu söyler misiniz lütfen yardım için teşekkürler :)
Yogi

1
@Yogi: İlk yanıta bakarsanız, yerel bildirimi iptal etmek istiyorsanız her seferinde döngü için koşmanız gerekir, ancak yukarıdaki yanıtta herhangi bir for döngüsü çalıştırmanıza gerek kalmaz, doğrudan yerel bildirime erişebilir ve bunu iptal edebilirsiniz yerel bildirim ve bunu Kullanıcı varsayılanlarından kaldırın,
Cevabıma göre

@JigneshBrahmkhatri Yönteminiz etkilidir. Ancak kullanıcı uygulamayı kaldırdığında ve yeniden yüklediğinde başarısız olur.
KingofBliss

@KingofBliss, bu durumda tüm bildirimleri iptal etmeliyiz, değil mi? Sanırım bu çözüm daha hızlı. :)
Sufian

@Sufian Tüm bildirimleri iptal etmek için çok daha hızlı bir yol var [[UIApplication sharedApplication] cancelAllLocalNotifications]; ;)
KingofBliss

8

İşte yaptığım şey.

Bildiriminizi oluştururken şunu yapın:

  // 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] ;

silmeye çalışırken şunu yapın:

 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

    }

}

Bu çözüm birden fazla bildirim için çalışmalı ve herhangi bir diziyi veya sözlüğü veya kullanıcı varsayılanlarını yönetmemeniz gerekir. Sistem bildirim veritabanına önceden kaydettiğiniz verileri kullanmanız yeterlidir.

Umarım bu, gelecekteki tasarımcılara ve geliştiricilere yardımcı olur.

Mutlu kod yazanlar! : D


Cevabınızı paylaştığınız için teşekkürler ama tüm bildirimleriniz aynı gövdeye sahipse veya gövde kullanıcıdan alınacaksa bu mantığın nasıl çalıştığını bu durumda kullanıcı aynı gövdeyi birden fazla bildirime verebilir.
Yogi

@Yogi, alertbody gibi, gerekli bildirimi almak için kontrol edebilir, bildirim.firedate yapabilirsiniz. basit bir çözüm için abhi'ye teşekkürler. u için 1 oy verin
Nazik

1
@NAZIK: Tartışmaya gösterdiğiniz ilgi için teşekkürler. Ancak yine de kullanıcı, bir alarm uygulaması olduğu için aynı yangın tarihinde iki bildirim planlayabilir. En azından bir test cihazı için bir test durumu olabilir ve bu çözüm orada başarısız görünüyor.
Yogi

@ Yogi, akıllıca test, neden kontrol edemiyoruz ([localNotification.alertBody isEqualToString: SavedTitle] || [localNotification.firedate == something]), çünkü aynı tarihli iki bildirim farklı alertBody içermelidir
Nazik

Bir bildirimi alertBodyveya fireDatebir bildirimi tanımlamak için kötüye kullanmayın ; userInfoBunu yapmak için alanı kullanın, cevap olarak @KingOfBliss ayrıntılar ...
severin

8

Hızlı bir şekilde zamanlama ve removeNotification:

    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)
        }
    }



}

1
Bir bildirimi alertBodyveya fireDatebir bildirimi tanımlamak için kötüye kullanmayın ; userInfoBunu yapmak için alanı kullanın, cevap olarak @KingOfBliss ayrıntılar ...
severin

Yes alertBody, bir bildirimi tanımlamak için iyi bir seçenek değildir. Bunu
userInfo olarak

6

iMOBDEV'in çözümü , belirli bir bildirimi kaldırmak için mükemmel bir şekilde çalışır (örn. alarmı sildikten sonra), ancak zaten tetiklenmiş ve hala bildirim merkezinde bulunan herhangi bir bildirimi seçerek kaldırmanız gerektiğinde özellikle yararlıdır.

Olası bir senaryo şöyle olabilir: bir alarm bildirimi devreye girer, ancak kullanıcı bu bildirime dokunmadan uygulamayı açar ve bu alarmı tekrar planlar. Belirli bir öğe / alarm için bildirim merkezinde yalnızca bir bildirimin olabileceğinden emin olmak istiyorsanız, bu iyi bir yaklaşımdır. Ayrıca, uygulama her açıldığında tüm bildirimleri temizlemenize gerek kalmaz, bu uygulamaya daha iyi uyacaktır.

  • Yerel bir bildirim oluşturduktan sonra, NSKeyedArchiverolduğu gibi saklamak için kullanın Data.UserDefaults . Bildirimin userInfo sözlüğünde kaydettiğiniz şeye eşit bir anahtar oluşturabilirsiniz. Bir Çekirdek Veri nesnesiyle ilişkiliyse, benzersiz nesne kimliği özelliğini kullanabilirsiniz.
  • İle alın NSKeyedUnarchiver . Artık cancelLocalNotification yöntemini kullanarak silebilirsiniz.
  • Anahtarı UserDefaultsuygun şekilde güncelleyin .

İşte bu çözümün Swift 3.1 sürümü (iOS 10'un altındaki hedefler için):

Mağaza

// 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")

Al ve sil

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")
}

Benim için çalıştı. Diğer tüm öneriler değil, çünkü dizi boş.
Maksim Kniazev

İOS 10 için bir fikriniz var mı?
Danpe

1
@Danpe: "Teslim Edilen Bildirimleri Yönetme" bölümüne bir göz atın: developer.apple.com/reference/usernotifications/…
Rygen

benim için Xcode'un işlediği küçük modlarla hızlı 3 ile çalıştı.
beshio

@beshio: uyarılar için teşekkürler. Söz dizimini güncelledim.
Rygen

5

Swift 4 çözümü:

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

4

Gerekirse Swift Sürümü:

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!")
            }
        }
    }

2

Bildirimi böyle planlarken kategori tanımlayıcısına sahip bir dize tutabilirsiniz.

        localNotification.category = NotificationHelper.categoryIdentifier

ve onu arayın ve gerektiğinde iptal edin

let  app = UIApplication.sharedApplication()

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

        }
    }

2

hızlı 3 tarzı:

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;
        }
    }
}

}

iOS 10 kullanımı için:

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

1

Geçtiğiniz cancelLocalNotification:UILocalNotification nesnesi, eşleşen özelliklerle mevcut herhangi bir UILocalNotification nesnesini eşleştirir.

Yani:

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

daha sonra iptal edilebilecek yerel bir bildirim sunacak:

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

1
Teşekkürler. Sanırım yeni bir bildirim oluşturuyorsunuz ve ardından iptal ediyorsunuz. Önceden planladığım bildirim üzerinde herhangi bir etkisi olmayacak ve yine de ateşlenecek.
Yogi

AlertBody dışında özellik ile eşleşen herhangi bir özellik var mı?
Shamsiddin

1

Bu işlevi Swift 2.0'da kullanıyorum:

  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
  }

@ KingofBliss'in Cevabından Esinlenilmiştir


0

Tekrarlanan Hatırlatmalar için (Örneğin, alarmınızın Paz, Cmt ve Çar saatlerinde 16: 00'da patlamasını istiyorsanız, 3 alarm yapmalı ve tekrarlama aralığını NSWeekCalendarUnit olarak ayarlamalısınız).

Yalnızca Bir Defa Hatırlatma yapmak için:

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];

Tekrarlanan Hatırlatma Yapmak İçin:

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

Size diziyi filtrelemek için.

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

Hatırlatıcıyı Sadece Bir Kez veya Tekrarlı olsa bile kaldırmak için:

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

}

0

KingofBliss'in cevabını biraz genişlettim, bunu biraz daha Swift2 benzeri yazdım, bazı gereksiz kodları kaldırdım ve bazı kaza korumalarını ekledim.

Başlamak için, bildirimi oluştururken, bildirimin kullanıcı kimliğini (veya herhangi bir özel özelliği) ayarladığınızdan emin olmanız gerekir userInfo:

notification.userInfo = ["uid": uniqueid]

Ardından, silerken şunları yapabilirsiniz:

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)'")
    }
}

1
Güvenlik için koruma ifadesi korumasını kullanabilirsiniz let app = UIApplication.sharedApplication () else {return false} for schedualedNotif in app.scheduledLocalNotifications {...} Bu durumda for-loop içinde açmaya zorlamanız gerekmez
troligtvis
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.