当 iOS 10 中 UNUserNotificationCenterDelegate 收到新通知时,如何删除之前发送的通知?

问题描述 投票:0回答:3

这个问题是关于 iOS 10 中新的

UserNotifications
框架。

我有一个应用程序,在用户在应用程序中执行特定操作后每半小时安排一次本地通知,从 1 小时开始。

为了避免用户的锁定屏幕或通知中心混乱,我只想一次显示一个通知,因此只有一个通知包含最新的相关信息。我的计划是在每次出现新通知时清除所有已发送的通知。

看起来这应该可以通过

willPresent
的新
UNUserNotificationCenterDelegate
方法实现,但它的行为并不像我预期的那样。

我调用以下函数来设置所有通知,从应用程序中事件发生后 1 小时开始,每半小时安排一次通知,直到事件发生后 23.5 小时发出最后一个通知:

func updateNotifications() {

    for hour in 1...23 {
        scheduleNotification(withOffsetInHours: Double(hour))
        scheduleNotification(withOffsetInHours: Double(hour) + 0.5)
    }
}

这是实际根据

mostRecentEventDate
安排通知的函数,这是在其他地方设置的
Date

func scheduleNotification(withOffsetInHours: Double) {

    // set up a Date for when the notification should fire
    let offsetInSeconds = 60 * 60 * withOffsetInHours
    let offsetFireDate = mostRecentEventDate.addingTimeInterval(offsetInSeconds)

    // set up the content of the notification
    let content = UNMutableNotificationContent()
    content.categoryIdentifier = "reminder"
    content.sound = UNNotificationSound.default()
    content.title = "Attention!"
    content.body = "It has been \(withOffsetInHours) hours since the most recent event."

    // set up the trigger
    let triggerDateComponents = Calendar.current.components([.year, .month, .day, .hour, .minute, .second], from: offsetFireDate)
    let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDateComponents, repeats: false)

    // set up the request
    let identifier = "reminder\(withOffsetInHours)"
    let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)

    // add the request for this notification
    UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in

        if error != nil {

            print(error)
        }
    })
}

在我的

UNUserNotificationCenterDelegate
中,我的
willPresent
方法设置如下:

func userNotificationCenter(_: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {

    print("will present...")

    UNUserNotificationCenter.current().removeAllDeliveredNotifications()

    withCompletionHandler([.alert,.sound])
}

我知道正在调用

willPresent
函数,因为它打印“将呈现...”,但通知中心中的现有通知不会被清除。有谁知道为什么这不起作用?或者是否有办法让它按照我想要的方式工作?


编辑:我想出了另一种方法来实现同样的目标,但它似乎也不起作用。

我的想法是使用

willPresent
使传入的预定通知静音,同时安排另一个通知立即到达(无需触发)。所有计划立即到达的通知都具有相同的标识符,因此应始终替换具有该标识符的现有通知,就像 this 2016 WWDC talk 中关于新 UserNotifications 框架的 20:00 左右的示例一样。这是我更新的
willPresent
方法:

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent: UNNotification, withCompletionHandler: (UNNotificationPresentationOptions) -> Void) {

    let identifier = willPresent.request.identifier

    if identifier != "reminder" {

        let offsetInHoursString = identifier.replacingOccurrences(of: "reminder", with: "")

        let content = UNMutableNotificationContent()
        content.categoryIdentifier = "reminder"
        content.sound = UNNotificationSound.default()
        content.title = "Attention!"
        content.body = "It has been \(offsetInHoursString) hours since the most recent event."

        let identifier = "hydrationReminder"

        let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)

        center.add(request, withCompletionHandler: { (error) in

            if error != nil {

                print(error)
            }
        })

        withCompletionHandler([])

    } else {

        withCompletionHandler([.alert,.sound])
    }
}

编辑:我终于意识到,

willPresent
只会在应用程序位于前台时被调用,正如它在此页面顶部所说的那样,所以这些方法实际上都不应该起作用。我以为每次收到通知都会调用willPresent。回到绘图板这个“仅最新、最相关的通知”的想法......


更新(2018 年 7 月):

随着 iOS 12 中分组通知的引入,更新旧通知(以减少通知混乱为目标)似乎不再那么重要。我仍然希望能够做到这一点,以尽量减少混乱的出现,而且远程推送通知(可以在事后更新)和本地通知(以后不能更新)之间似乎应该具有功能对等性。然而,由于苹果引入了分组通知,我预计他们不太可能实现更新旧本地通知的功能,而是让应用程序只发送新通知并将它们与现有通知分组在一起。

ios notifications ios10 unusernotificationcenter
3个回答
2
投票
演示

我想你要实现的功能叫“更新通知”。

iOS 10 允许更新通知。您只需要做的就是——保持通知具有相同的

标识符

让我们看一下演示:

第一个通知:

NSURL * imageUrl = [[NSBundle mainBundle] URLForResource:@"dog" withExtension:@"png"]; UNNotificationAttachment *imgAtt = [UNNotificationAttachment attachmentWithIdentifier:@"image" URL:imageUrl options:nil error:&error]; NSURL * mp4Url = [[NSBundle mainBundle] URLForResource:@"media" withExtension:@"mp4"]; UNNotificationAttachment *mediaAtt = [UNNotificationAttachment attachmentWithIdentifier:@"image" URL:mp4Url options:nil error:&error]; UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc]init]; //在通知中心显示的总是第一个多媒体资源 content.attachments = @[imgAtt,mediaAtt]; content.badge = @1; content.title = @"Wake Up"; content.subtitle = @"First time"; content.body = @"next time。。。 "; content.categoryIdentifier = @"wakeup"; content.launchImageName = @"dog"; content.sound = [UNNotificationSound defaultSound]; // content.threadIdentifier = @""; content.userInfo = @{@"first":@"5:00 am",@"second":@"6:00"}; UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5.0 repeats:NO]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"com.junglesong.pushtestdemo.wakeup" content:content trigger:trigger]; [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { NSLog(@"wake up message has been deliverd!"); }];

更新第一个通知:

UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc]init]; content.badge = @1; content.title = @"Update!dear,wake up"; content.subtitle = @"Update! dear,please"; content.body = @"Update!shall we have breakfast?"; content.categoryIdentifier = @"wakeup"; content.launchImageName = @"dog"; content.sound = [UNNotificationSound defaultSound]; // content.threadIdentifier = @""; content.userInfo = @{@"first":@"5:00 am",@"second":@"6:00"}; UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:5.0 repeats:NO]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"com.junglesong.pushtestdemo.wakeup" content:content trigger:trigger]; [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { NSLog(@"wake up message has been updated!"); }];

现在,你添加了两个通知。但是系统将它们视为相同。所以只有一个。第二个通知取代了第一个。在 iOS 10 中,称之为

update

“identifier”属性是UNNotificationRequest的id,可以区分通知。


0
投票
removeDeliveredNotifications(withIdentifiers:)


0
投票
userDefaults

将所有标识符存储在数组中,然后使用 removeDeliveredNotifications(withIdentifiers:)

 控制它们
    

© www.soinside.com 2019 - 2024. All rights reserved.