12

这个问题是关于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)
    }
}

这是实际基于 调度通知的函数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使传入的预定通知静音,同时安排另一个通知立即到达(没有触发器)。所有计划立即到达的通知都具有相同的标识符,因此应始终替换具有该标识符的现有通知,例如在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])
    }
}

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


更新(2018 年 7 月):随着在 iOS 12 中引入分组通知,更新旧通知(目的是减少通知混乱)似乎不太相关。我仍然希望能够这样做以最大程度地减少混乱的出现,并且似乎可以在事后更新的远程推送通知和以后无法更新的本地通知之间具有功能奇偶性。但是,由于 Apple 引入了分组通知,我预计他们不太可能实现更新旧本地通知的能力,而是让应用程序只发送新通知并将它们与现有通知组合在一起。

4

2 回答 2

1

你可以查看这个demo。</p>

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

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

让我们看一个演示:

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

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

于 2016-09-26T03:49:11.860 回答
0

您可以只使用removeDeliveredNotifications(withIdentifiers:)

于 2016-08-20T13:39:20.837 回答