Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/118.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当新通知在iOS 10中以UnuseNotificationCenterDelegate的形式到达时,如何删除以前传递的通知?_Ios_Notifications_Ios10_Unusernotificationcenter - Fatal编程技术网

当新通知在iOS 10中以UnuseNotificationCenterDelegate的形式到达时,如何删除以前传递的通知?

当新通知在iOS 10中以UnuseNotificationCenterDelegate的形式到达时,如何删除以前传递的通知?,ios,notifications,ios10,unusernotificationcenter,Ios,Notifications,Ios10,Unusernotificationcenter,这个问题是关于iOS 10中新的UserNotifications框架的 我有一个应用程序,在用户在应用程序中执行特定操作后,每半小时安排一次本地通知,从1小时开始 为了避免弄乱用户的锁屏或通知中心,我一次只希望显示一个通知,因此只有一个通知包含最新的相关信息。我的计划是在提交新通知时清除所有已发送的通知 这似乎可以通过新的willPresent方法UNUserNotificationCenterDelegate实现,但它的行为并不像我预期的那样 我调用以下函数设置所有通知,从应用程序中事件发生

这个问题是关于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
安排通知的功能,该日期是在其他地方设置的
日期

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
使传入的计划通知静音,同时安排另一个通知立即到达(无触发器)。计划立即到达的所有通知都具有相同的标识符,因此应始终替换具有该标识符的现有通知,如关于new UserNotifications framework中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中分组通知的引入,更新较旧的通知(目的是减少通知混乱)似乎不太相关。我仍然希望能够做到这一点,以尽量减少混乱的外观,而且似乎应该在远程推送通知(可以在事后更新)和本地通知(以后无法更新)之间实现功能对等。然而,由于苹果公司已经引入了分组通知,我认为他们不太可能实现更新旧本地通知的功能,而是让应用程序只发送新的通知,并将它们与现有通知组合在一起。

你可以使用它

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

iOS 10允许更新通知。您所要做的就是保持通知具有相同的标识符

让我们看一个演示:

  • 第一次通知:
  • NSURL*imageUrl=[[NSBundle mainBundle]URLForResource:@“dog”带扩展名:@“png”];
    UNNotificationAttachment*imgAtt=[UNNotificationAttachment attachmentWithIdentifier:@“image”URL:imageUrl选项:无错误:&错误];
    NSURL*mp4Url=[[NSBundle mainBundle]URLForResource:@“媒体”,扩展名:@“mp4”];
    UNNotificationAttachment*mediaAtt=[UNNotificationAttachment attachmentWithIdentifier:@“image”URL:mp4Url选项:无错误:&错误];
    UNMutableNotificationContent*内容=[[UNMutableNotificationContent alloc]init];
    //在通知中心显示的总是第一个多媒体资源
    content.attachments=@[imgAtt,mediaAtt];
    content.badge=@1;
    content.title=@“唤醒”;
    content.subtitle=@“第一次”;
    content.body=@“下次…”;
    content.categoryIdentifier=@“唤醒”;
    content.launchImageName=@“dog”;
    content.sound=[unnotificationsounddefaultsound];
    //content.threadIdentifier=@”;
    content.userInfo=@{@“first”:@“上午5:00”,@“second”:@“6:00”};
    UNTimeIntervalNotificationTrigger*trigger=[UntimeIntervalNotificationTriggerWithTimeInterval:5.0重复:否];
    UNNotificationRequest*request=[UnnotificationRequestRequestWithIdentifier:@“com.junglesong.pushtestdemo.wakeup”内容:内容触发器:触发器];
    [[UNUserNotificationCenter currentNotificationCenter]添加NotificationRequest:RequestWithCompletionHandler:^(NSError*\u可为空错误){
    NSLog(@“已发送唤醒消息!”);
    
    }];这是清除通知的正确功能,但问题在于触发它。这里的问题是,当传递非远程通知且应用程序不在前台时,没有调用的方法,因此当传递通知以清除旧的已传递通知时,没有地方调用该方法。找到解决方案了吗?同样的问题。@gohnjanotis不确定这是否有帮助,但请看我的答案@Justin我还没有找到解决方案。我不认为有什么方法可以用当前的API实现我想要的。@亲爱的,如果你建议在userNotificationCenter(uU2;:didReceive:withCompletionHandler:)中实现通知清除代码,那将不会得到期望的结果,因为该函数仅在用户执行