当 iOS 10 中的 UNUserNotificationCenterDelegate 收到新通知时,如何删除以前发送的通知? [英] How can I remove previously delivered notifications when a new notification arrives with UNUserNotificationCenterDelegate in iOS 10?

查看:27
本文介绍了当 iOS 10 中的 UNUserNotificationCenterDelegate 收到新通知时,如何删除以前发送的通知?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This question is about the new UserNotifications framework in iOS 10.

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

I have an app that schedules a local notification every half hour after the user did a certain action in the app, starting at 1 hour.

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

To avoid cluttering a user's lock screen or notification center, I only want one notification to show up at a time, so there is only one notification with the most recent, relevant information. My plan to achieve this is to clear all delivered notifications any time a new notification is presented.

看起来这应该可以通过 UNUserNotificationCenterDelegate 的新 willPresent 方法实现,但它的行为不像我预期的那样.

It seems this should be possible with the new willPresent method of UNUserNotificationCenterDelegate, but it's not behaving as I would expect.

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

Here's a function that I call to set up all the notifications, starting at 1 hour after the event in the app, and scheduling a notification every half hour until the last one at 23.5 hours after the event:

func updateNotifications() {

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

这是根据 mostRecentEventDate 实际安排通知的函数,它是在别处设置的 Date:

This is the function that actually schedules the notifications based on the mostRecentEventDate, which is a Date set elsewhere:

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 方法设置如下:

In my UNUserNotificationCenterDelegate I have the willPresent method set up like this:

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

    print("will present...")

    UNUserNotificationCenter.current().removeAllDeliveredNotifications()

    withCompletionHandler([.alert,.sound])
}

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

I know the willPresent function is being called because it prints "will present..." but the existing notifications in the notification center don't get cleared. Does anyone know why this doesn't work? Or if there's a way to get it working the way I want it to?

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

I came up with an alternate approach to achieve the same thing, but it also doesn't seem to work.

我的想法是使用 willPresent 使传入的预定通知静音,同时安排另一个通知立即到达(没有触发器).计划立即到达的所有通知都具有相同的标识符,因此应始终替换具有该标识符的现有通知,例如 2016 年 WWDC 演讲关于新的 UserNotifications 框架.这是我更新的 willPresent 方法:

My idea here was to use willPresent to silence the incoming scheduled notification while scheduling another notification to arrive immediately (without a trigger). All the notifications being scheduled to arrive immediately have the same identifier, so the existing notification with that identifier should always be replaced, like in the example around 20:00 in this 2016 WWDC talk about the new UserNotifications framework. Here's my updated willPresent method:

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.回到这个只有最新、最相关的通知"想法的绘图板......


I finally realized that willPresent will only be called if the app is in the foreground, as it says right at the top of this page, so neither of these approaches should actually work. I thought willPresent would be called every time a notification was received. Back to the drawing board on this "only the newest, most relevant notification" idea...

更新(2018 年 7 月):随着 iOS 12 中分组通知的引入,更新旧通知(以减少通知混乱为目标)似乎不太重要.我仍然希望能够做到这一点以尽量减少混乱的出现,而且似乎可以在事后更新的远程推送通知和以后无法更新的本地通知之间存在功能奇偶校验.然而,由于 Apple 已经引入了分组通知,我预计他们不太可能实现更新旧的本地通知的能力,而是让应用程序只发送新通知并将它们与现有通知组合在一起.

UPDATE (July 2018): With the introduction of grouped notifications in iOS 12, updating an older notification (with the goal of reducing notification clutter) seems less relevant. I'd still like to be able to do it to minimize the appearance of clutter, and it seems there should be feature parity between remote push notifications, which can be updated after the fact, and local notifications, which can not be updated later. However, since Apple has introduced grouped notifications, I'd expect its less likely they'd implement the ability to update old local notifications in favor of letting apps just send new ones and having them group together with existing notifications.

推荐答案

你可以查看这个demo.

我想你要实现的功能叫做更新通知".

I think you want to achieve the function is called "update notification".

iOS 10 允许更新通知.您只需要做的——保持通知具有相同的标识符.

iOS 10 allow update the notification.All you just do——keep the notifications have the same identifier.

让我们看一个演示:

  1. 第一次通知:

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

  1. 更新第一个通知:

    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 中,调用此更新.

Now, you add two notification.But the system treats them as the same.So there is just only one.And the sencond replaces the first one.In iOS 10,call this update.

属性identifier"是UNNotificationRequest的id,可以区分通知.

The property "identifier" is the id of UNNotificationRequest,which can differentiate notifications.

这篇关于当 iOS 10 中的 UNUserNotificationCenterDelegate 收到新通知时,如何删除以前发送的通知?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆