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

时间:2016-08-12 16:45:27

标签: ios notifications ios10 unusernotificationcenter

这个问题与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函数,因为它打印“将显示...”但通知中心的现有通知不会被清除。有谁知道为什么这不起作用?或者,如果有办法让它以我想要的方式运作?

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

我的想法是使用willPresent来静音传入的预定通知,同时安排另一个通知立即到达(没有触发器)。计划立即到达的所有通知都具有相同的标识符,因此应始终替换具有该标识符的现有通知,例如this 2016 WWDC talk中关于新UserNotifications框架的20:00左右的示例。这是我更新的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只会调用,正如它在{{ 3}},所以这些方法都不应该真正起作用。我想每次收到通知都会调用<div class="container"> <div class="row well"> <div class="text-center"> <h2>Create</h2> <h4>Create Advert</h4> </div> </div> <div class="form-horizontal"> <div class="text-danger"></div> <div class="row"> <div class="col-xs-6"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">Email</label> <div class="col-sm-10"> <input type="email" class="form-control" id="inputEmail3" placeholder="Email"> </div> </div> </div> <div class="col-xs-6"> <div class="form-group"> <label for="inputPassword3" class="col-sm-2 control-label">Password</label> <div class="col-sm-10"> <input type="password" class="form-control" id="inputPassword3" placeholder="Password"> </div> </div> </div> </div> </div> 。回到绘图板上这个“只有最新,最相关的通知”的想法...

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

2 个答案:

答案 0 :(得分:1)

您可以查看demo

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

iOS 10允许更新通知。您只需这样做 - 保持通知具有相同的标识符

让我们看一个演示:

  1. 第一次通知:
  2.     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. 更新第一个通知:
    2.     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中,调用更新。< / p>

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

答案 1 :(得分:0)