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

查看:234
本文介绍了在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.

新的 willPresent似乎应该可以实现这一点。 UNUserNotificationCenterDelegate 的方法,但它的行为并不像我预期的那样。

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 实际安排通知的功能,这是在其他地方设置的日期

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...

UPDATE (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.

推荐答案

你可以查看这个演示

我认为你想要实现的功能称为更新通知。

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

现在,您添加两个通知。但系统将它们视为一样。所以只有一个。而sencond取代了第一个。在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天全站免登陆