Hapus pemberitahuan lokal tertentu

92

Saya mengembangkan aplikasi alarm iPhone berdasarkan pemberitahuan lokal.

Saat menghapus alarm, pemberitahuan lokal terkait harus dibatalkan. Tetapi bagaimana saya bisa menentukan dengan tepat objek mana dari larik notifikasi lokal yang akan dibatalkan?

Saya mengetahui [[UIApplication sharedApplication] cancelLocalNotification:notification]metodenya tetapi bagaimana saya bisa mendapatkan 'pemberitahuan' ini untuk membatalkannya?

Yogi
sumber

Jawaban:

217

Anda dapat menyimpan nilai unik untuk kunci di info pengguna pemberitahuan lokal Anda. Dapatkan semua notifikasi lokal, putar melalui array dan hapus notifikasi tertentu.

Kode sebagai berikut,

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

CEPAT:

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:

Jika Anda menggunakan UserNotification (iOS 10+), cukup ikuti langkah-langkah ini:

  1. Saat membuat konten UserNotification, tambahkan pengenal unik

  2. Hapus pemberitahuan tertentu yang tertunda menggunakan removePendingNotificationRequests (withIdentifiers :)

  3. Hapus pemberitahuan tertentu yang dikirim menggunakan removeDeliveredNotifications (withIdentifiers :)

Untuk info selengkapnya, UNUserNotificationCenter

KingofBliss
sumber
@ kingofBliss, bisakah kamu memberitahu saya untuk memberikan di sana di "uidtodelete". karena itu tidak dideklarasikan dalam kasus saya.
ishhhh
@ishhh itsjust a strig value .. Anda harus mendeklarasikannya dan menginisialisasi dengan nilai uid yang akan dihapus
KingofBliss
@ kingofBliss, uid selalu menunjukkan null di NSLog. tidak tahu bagaimana cara menyingkirkan ini. Tolong bantu saya
ishhhh
@ishhh sudahkah Anda menyimpan nilai apa pun untuk uid di kamus userinfo saat membuat pemberitahuan lokal? Saya pikir Anda melewatkannya.
KingofBliss
@kingofBliss, "uid" itu adalah nama variabel Anda sendiri, Anda dapat menggunakan nama penting apa pun seperti "notificationID", dan menyimpannya di a NSDictionarydengan nilai id entitas yang terkait dengan UILocalNotification. Kemudian setel properti notification.userInfo ke kamus dengan data khusus Anda. Sekarang ketika Anda mendapatkan pemberitahuan, Anda dapat membedakannya dengan id khusus itu atau apa pun yang Anda butuhkan.
IgniteCoders
23

Pilihan lain:

Pertama-tama, ketika Anda membuat pemberitahuan lokal, Anda dapat menyimpannya di default pengguna untuk penggunaan di masa mendatang, Objek pemberitahuan lokal tidak dapat disimpan langsung di default pengguna, Objek ini perlu diubah menjadi objek NSData terlebih dahulu, dan kemudian NSDatadapat disimpan ke User defaults. Di bawah ini adalah kode untuk itu:

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

Setelah Anda menyimpan dan menjadwalkan pemberitahuan lokal, Di masa mendatang, mungkin timbul persyaratan bahwa Anda perlu membatalkan pemberitahuan yang Anda buat sebelumnya, sehingga Anda dapat mengambilnya dari default Pengguna.

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

Semoga ini membantu

iMOBDEV
sumber
Terima kasih, saya telah menerapkannya dengan cara pertama tetapi jawaban Anda juga benar. Saya akan mempertimbangkan hal ini. Bisakah Anda memberi tahu mana yang lebih efisien? Terima kasih atas bantuannya :)
Yogi
1
@Yogi: Jika Anda melihat jawaban pertama, Anda perlu menjalankan loop setiap kali jika Anda ingin membatalkan notifikasi lokal, tetapi dalam jawaban di atas, Anda tidak perlu menjalankan loop for apa pun, Anda dapat langsung mengakses notifikasi lokal dan membatalkannya pemberitahuan lokal dan hapus dari default Pengguna, Sesuai jawaban saya, ini cara yang lebih efisien
iMOBDEV
@JigneshBrahmkhatri Metode Anda efektif. Tetapi itu akan gagal ketika pengguna menghapus aplikasi, dan menginstalnya kembali.
KingofBliss
@KingBliss, dalam hal ini kita harus membatalkan semua notifikasi, bukan? Jadi saya kira solusi ini lebih cepat. :)
Sufian
@Sufian Untuk membatalkan semua notifikasi ada cara yang jauh lebih cepat [[UIApplication sharedApplication] cancelAllLocalNotifications]; ;)
KingofBliss
8

Inilah yang saya lakukan.

Saat membuat notifikasi Anda, lakukan ini:

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

ketika mencoba untuk menghapusnya lakukan ini:

 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

    }

}

Solusi ini harus berfungsi untuk beberapa pemberitahuan, dan Anda tidak mengelola array atau kamus atau default pengguna. Anda cukup menggunakan data yang telah Anda simpan ke database pemberitahuan sistem.

Semoga ini membantu desainer dan pengembang masa depan.

Selamat coding guys! : D

abhi
sumber
Terima kasih telah membagikan jawaban Anda tetapi bagaimana logika ini bekerja jika semua notifikasi Anda memiliki isi yang sama atau jika isi akan diambil dari pengguna. Dalam hal ini pengguna dapat memberikan isi yang sama ke beberapa notifikasi.
Yogi
@Yogi, seperti alertbody, Anda dapat memeriksa, notification.firedate untuk mendapatkan notifikasi yang diperlukan. terima kasih kepada abhi untuk solusi sederhana.
suara positif
1
@ Nazik: Terima kasih atas minat Anda dalam diskusi. Namun pengguna tetap dapat menjadwalkan dua pemberitahuan pada tanggal kebakaran yang sama karena itu adalah aplikasi alarm. Setidaknya ini bisa menjadi kasus uji untuk penguji dan solusi ini tampaknya gagal di sana.
Yogi
@ Yogi, pengujian yang bijak, mengapa kita tidak bisa memeriksa apakah ([localNotification.alertBody isEqualToString: saveTitle] || [localNotification.firedate == sesuatu]), karena dua pemberitahuan dengan tanggal yang sama harus berisi alertBody yang berbeda
Nazik
Jangan menyalahgunakan alertBodyatau fireDateuntuk mengidentifikasi pemberitahuan; gunakan userInfobidang untuk melakukan ini, sebagai jawaban oleh detail @KingOfBliss ...
severin
8

Menjadwalkan dan menghapus Notifikasi dengan cepat:

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



}
Roman Barzyczak
sumber
1
Jangan menyalahgunakan alertBodyatau fireDateuntuk mengidentifikasi pemberitahuan; gunakan userInfobidang untuk melakukan ini, sebagai jawaban oleh detail @KingOfBliss ...
severin
Ya alertBody bukanlah pilihan yang baik untuk mengidentifikasi pemberitahuan. Saya mengubahnya menjadi userInfo
Roman Barzyczak
6

iMOBDEV ini solusi bekerja sempurna untuk menghapus pemberitahuan tertentu (misalnya setelah menghapus alarm) tapi itu khusus berguna ketika Anda perlu selektif menghapus pemberitahuan yang telah dipecat dan masih di pusat pemberitahuan.

Skenario yang mungkin adalah: notifikasi untuk alarm diaktifkan, tetapi pengguna membuka aplikasi tanpa mengetuk notifikasi itu dan menjadwalkan alarm itu lagi. Jika Anda ingin memastikan hanya satu notifikasi yang dapat berada di pusat notifikasi untuk item / alarm tertentu, itu adalah pendekatan yang baik. Ini juga memungkinkan Anda tidak harus menghapus semua notifikasi setiap kali aplikasi dibuka, jika itu lebih sesuai dengan aplikasi.

  • Setelah membuat pemberitahuan lokal, gunakan NSKeyedArchiveruntuk menyimpannya seperti Datadi UserDefaults. Anda dapat membuat kunci yang sama dengan yang Anda simpan di kamus userInfo notifikasi. Jika dikaitkan dengan objek Data Inti, Anda dapat menggunakan properti objectID uniknya.
  • Ambil kembali dengan NSKeyedUnarchiver. Sekarang Anda dapat menghapusnya menggunakan metode cancelLocalNotification.
  • Perbarui kunci yang UserDefaultssesuai.

Berikut adalah versi Swift 3.1 dari solusi itu (untuk target di bawah iOS 10):

Toko

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

Ambil dan hapus

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")
}
Rygen
sumber
Bekerja untuk saya. Tidak semua saran lain, karena larik kosong.
Maksim Kniazev
Ada ide untuk iOS 10?
Danpe
1
@Danpe: lihat bagian "Mengelola Pemberitahuan yang Dikirim" di sini: developer.apple.com/reference/usernotifications/…
Rygen
bekerja untuk saya dengan swift 3 dengan mod kecil, yang ditangani Xcode.
beshio
@beshio: terima kasih atas perhatiannya. Saya telah memperbarui sintaksnya.
Rygen
5

Solusi Swift 4:

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

Versi Swift, jika perlu:

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!")
            }
        }
    }
Sohil R. Memon
sumber
2

Anda dapat menyimpan string dengan pengenal kategori saat menjadwalkan notifikasi seperti itu

        localNotification.category = NotificationHelper.categoryIdentifier

dan telusuri dan batalkan jika diperlukan seperti itu

let  app = UIApplication.sharedApplication()

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

        }
    }
pantos 27
sumber
2

gaya cepat 3:

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

}

untuk penggunaan iOS 10:

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

Objek UILocalNotification yang Anda teruskan cancelLocalNotification:akan cocok dengan objek UILocalNotification yang ada dengan properti yang cocok.

Begitu:

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

akan menampilkan pemberitahuan lokal yang nantinya dapat dibatalkan dengan:

UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = @"foo";
[[UIApplication sharedApplication] cancelLocalNotification:notification];
jhibberd.dll
sumber
1
Terima kasih. Saya rasa Anda membuat pemberitahuan baru dan kemudian membatalkannya. Ini tidak akan berpengaruh pada pemberitahuan yang saya jadwalkan sebelumnya dan masih akan diaktifkan.
Yogi
Apakah ada properti yang bisa menjadi properti yang cocok kecuali alertBody?
Shamsiddin
1

Saya menggunakan fungsi ini di 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
  }

Terinspirasi dari Jawaban @ KingofBliss

MBH
sumber
0

Untuk Pengingat Berulang (Misalnya Anda ingin alarm Anda menyala pada Minggu, Sabtu, dan Rabu pada pukul 16:00, Kemudian Anda harus membuat 3 alarm dan mengatur repeatInterval ke NSWeekCalendarUnit).

Untuk membuat Once Only Reminder:

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

Untuk Membuat Pengingat Berulang:

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

Untuk Memfilter array Anda untuk menampilkannya.

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

Untuk menghapus Pengingat meskipun hanya Sekali atau Berulang:

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

}
Abo3atef
sumber
0

Saya memperluas jawaban KingofBliss sedikit, menulis ini sedikit lebih mirip Swift2, menghapus beberapa kode yang tidak perlu, dan menambahkan beberapa pelindung kerusakan.

Untuk memulai, saat membuat notifikasi, Anda perlu memastikan bahwa Anda menyetel uid (atau properti khusus lainnya) dari notifikasi userInfo:

notification.userInfo = ["uid": uniqueid]

Kemudian, saat menghapusnya, Anda dapat melakukan:

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)'")
    }
}
brandonscript
sumber
1
Untuk keamanan Anda bisa menggunakan penjaga-penjaga pernyataan membiarkan aplikasi = UIApplication.sharedApplication () else {return false} untuk schedualedNotif di app.scheduledLocalNotifications {...} Maka Anda tidak perlu kekuatan unwrap dalam untuk loop
troligtvis