首页 文章

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

提问于
浏览
10

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

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

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

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

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

func updateNotifications() {

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

这是实际根据 mostRecentEventDate 调度通知的函数, 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 函数,因为它打印"will present..."但通知中心的现有通知不起作用?或者,如果有办法让它以我想要的方式运作?


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

我的想法是使用 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])
    }
}

EDIT: 我终于意识到 willPresent 只会在应用程序位于前台时被调用,正如它在this page的顶部所说的那样,所以这些方法都不应该真正起作用 . 我以为每次收到通知都会调用 willPresent . 回到这个"only the newest, most relevant notification"想法的绘图板......


UPDATE (July 2018): 随着iOS 12中分组通知的引入,更新旧通知(目标是减少通知混乱)似乎不太相关 . 我希望它们不太可能实现更新旧的本地通知的能力,而是让应用程序只发送新的通知并让它们与现有通知组合在一起 .

2 回答

  • 0

    你可以查看demo .

    我想你想实现的功能叫做“更新通知” .

    iOS 10允许更新通知 . 您只需执行 - 保持通知具有相同的 identifier .

    我们来看一个演示:

    • 第一次通知:
    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!");
        }];
    

    现在,你添加了两个通知 . 但系统将它们视为相同 . 所以只有一个 . 而sencond取代了第一个 . 在iOS 10中,调用它 update .

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

  • 1

相关问题