在iOS 10中使用UNUserNotificationCenterDelegate收到新通知时,如何删除以前发送的通知?

goh*_*tis 11 notifications ios ios10 unusernotificationcenter

这个问题是关于UserNotificationsiOS 10中的新框架.

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

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

看来这应该是可行的新willPresent方法UNUserNotificationCenterDelegate,但它的行为并不像我期望的那样.

这是一个函数,我打电话设置所有通知,从应用程序中的事件后1小时开始,并在事件发生后23.5小时每半小时安排一次通知,直到最后一个通知:

func updateNotifications() {

    for hour in 1...23 {
        scheduleNotification(withOffsetInHours: Double(hour))
        scheduleNotification(withOffsetInHours: Double(hour) + 0.5)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是根据实际进度通知的功能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)
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

在我UNUserNotificationCenterDelegate我的willPresent方法设置如下:

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

    print("will present...")

    UNUserNotificationCenter.current().removeAllDeliveredNotifications()

    withCompletionHandler([.alert,.sound])
}
Run Code Online (Sandbox Code Playgroud)

我知道willPresent正在调用该函数,因为它打印"将显示..."但通知中心中的现有通知不会被清除.有谁知道为什么这不起作用?或者,如果有办法让它以我想要的方式运作?


编辑:我想出了另一种方法来实现同样的目的,但它似乎也没有用.

我的想法是用来willPresent静音传入的预定通知,同时安排另一个通知立即到达(没有触发器).计划立即到达的所有通知都具有相同的标识符,因此应始终替换具有该标识符的现有通知,例如2016年WWDC关于新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])
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:我终于意识到只有当应用程序位于前台willPresent才会被调用,正如它在本页顶部所说的那样,所以这些方法都不应该真正起作用.我以为willPresent每次收到通知都会被调用.回到绘图板上这个"只有最新,最相关的通知"的想法......


更新(2018年7月):随着iOS 12中分组通知的引入,更新旧通知(目标是减少通知混乱)似乎不太相关.我仍然希望能够最大限度地减少混乱的外观,并且似乎应该在事后可以更新的远程推送通知和稍后无法更新的本地通知之间存在功能奇偶校验.但是,由于Apple已经引入了分组通知,我认为它们不太可能实现更新旧本地通知的能力,而是让应用程序只发送新通知并让它们与现有通知组合在一起.

Owe*_*hao 0

您可以只使用removeDeliveredNotifications(withIdentifiers:)

  • 这是清除通知的正确功能,但问题在于触发它。这里的问题是,当传递非远程通知并且应用程序不在前台时,没有任何方法被调用,因此当传递通知以清除旧的已传递通知时,没有地方可以调用该方法。 (4认同)