如何清除 iOS 的远程推送通知?

Posted

技术标签:

【中文标题】如何清除 iOS 的远程推送通知?【英文标题】:How to clear a remote pushed notification for iOS? 【发布时间】:2017-10-11 13:23:58 【问题描述】:

所以我一直在阅读远程通知,并终于让它工作了;我们的应用程序正在从我们的服务器接收通知。如果我们的服务器上满足特定条件(例如通知不再有效),我们现在想要删除或更新未读通知。我知道“无声”通知是唯一的方法,但我仍然对如何做感到困惑。 如果静默通知触发我的应用唤醒,我可以安排本地通知,但我可以删除已经存在的远程通知吗?

唯一的解决方案是专门使用来自服务器的静默通知,并将所有通知安排为带有自定义标识符的本地通知,我以后可以将其删除? 例如,如果我想要这个功能,我可以永远不要使用从我的服务器到设备的 fire&forget 远程推送通知吗?

编辑:此应用支持低至 iOS 9:/

【问题讨论】:

【参考方案1】:

我最终按照his answer 中建议的 TawaNicolas 进行操作,通过使用getDeliveredNoti.... 获取收到的通知,然后检查每个通知的 userInfo 以找到我想要删除的通知。我将可移动通知的标识符存储在一个数组中,并调用removeDelivered...

这正是他的回答所暗示的,但一开始并没有奏效,我很难找出原因。我仍然不能完全确定我是否已修复它,但我的测试表明它正在工作 - 我的解决方案有点道理。

问题是,在didReceiveRemote.. 函数中,你必须在最后调用completionHandler(.newData)。这是为了通知 NotificationCenter 发生了一些变化。我开始怀疑这个回调是在 可移动通知实际被删除之前调用的。我检查了文档,removeDeliveredNotifications 确实是异步的。这意味着当我这样做时:

UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: removableIDs)
completionHandler(.newData)

不保证第一个函数在调用第二个函数之前完成。这意味着 completionHandler 告诉我的 NotificationCenter 某些内容已经更新,首先完成,然后通知从系统中删除。 (NotificationCenter 显然不会在该函数之后调用自己的 completionHandler 来更新 UI)。

所有这些可能会或可能不会发生。正如我所经历的那样;当连接到调试器时,removeDeliveredNotifications 函数非常快,以至于它总是在调用completionHandler 之前完成,这意味着在更新系统之前通知已被删除。所以在开发这个时一切看起来都很棒。当我与调试器断开连接时,removeDeliveredNotifications-函数稍微慢了一点,并且由于它是异步的,它在我调用 completionHandler 之后完成 - 导致系统更新得太快。 p>

解决此问题的最佳方法是 Apple 为 removeDeliveredNotifications 提供一个 completionBlock,并在其中调用我们的 completionHandler,但他们没有。

为了解决这个问题,我现在添加了 0.2 秒的固定延迟。它可能低于 0.2,但对于我们正在做的事情来说,它并不重要。

这是我创建的一个类和函数,可以轻松地从任何地方延迟某些东西:

class RuntimeUtils
    class func delay(seconds delay:Double, closure:@escaping ()->())
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(delay*Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure)
    

这里我在didReceiveRemoteNotification:AppDelegate中使用它:

UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: removableIDs)
RuntimeUtils.delay(seconds: 0.2, closure: 
    completionHandler(.newData)
)

将这个延迟添加到completionHandler后,它总是在我删除通知后执行,并且似乎每次都有效,无论是否连接了调试器。

这是一个令人作呕的问题,而且修复得很糟糕。

【讨论】:

感谢您的详细回答,我刚刚在我们的应用程序中实现了相同的功能,并将报告您的延迟修复是否也需要在 prd 中进行。如果没有调试器,它在本地开发设置中仍然可以正常工作,但让我们看看。 @mitschmidt 这是 4 年前的事了。你真的还需要支持 ios 9 吗?如果没有,还有其他解决方案。 确实它在没有解决方法的情况下工作,到目前为止可靠。仍然感谢您的文档和努力。【参考方案2】:

在您的应用从静默通知中唤醒后,您需要使用以下命令循环接收到的通知:

目标-C:

[[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) 

];

斯威夫特:

UNUserNotificationCenter.current().getDeliveredNotifications  (notifications: [UNNotification]) in


然后检查每个通知的request.content.userInfo 属性,以确定是否是您要删除的通知。

然后,您使用以下命令将其从通知中心删除:

目标-C:

[[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:@[identifier]];

斯威夫特:

UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [identifier])

其中identifiernotification.request.identifier 属性。

编辑:如果您想识别正确的通知,您必须找出您在userInfo 中可以识别正确通知的有效负载中发送的内容。 (可能是用户 ID 或事件 ID?这取决于您的项目。)

【讨论】:

好提示!每个通知都将包含一个自定义 ID 字段,以识别应该删除哪些。但是,这个应用程序必须支持到 iOS 9,据我所知,我不能使用 UNUserNotificationCenter :( 但一个很好的答案! @Sti 谢谢你,老实说,你必须在这方面支持 iOS 9,这很糟糕。因为我认为在 iOS 10 之前这是不可能的。但无论如何,您可以使用 iOS 10 及更高版本使您的应用程序支持此功能,但对于 iOS 9,它应该具有默认行为,这意味着应用程序会清除所有通知当它进入前台时。 Followup-question.. 应用程序的哪一部分从无声通知中“唤醒”?我不明白我应该把他的代码放在哪里.. @Sti 我不确定,但我认为这是处理它的方法:developer.apple.com/documentation/uikit/uiapplicationdelegate/… 嘿,我最终为 iOS 10+ 执行此操作,但我遇到了一些奇怪的事情。当我连接到调试器时,一切正常,但在 AdHoc/TestFlight 中安装此应用程序时/AppStore 似乎我的“背景”工作根本没有发生。我只是在实现didReceiveRemoteNotification... 并使用getDeliveredNotifications,找到与我的相关用户信息值匹配的任何通知,并使用其他ID 调用removeDeliveredNotifications,而不是最后一个。这在连接到调试器时工作得很好,但在测试版本时似乎有 10% 的时间工作【参考方案3】:

对于 iOS >= 10,您可以使用 UNUserNotificationCenter.current().getDeliveredNotifications 和/或 UNUserNotificationCenter.current().removeAllDeliveredNotifications

您还必须添加import UserNotifications,这是一个不错的新通知框架。

【讨论】:

天哪,看起来不错,但我们的应用必须支持到 iOS 9 :(

以上是关于如何清除 iOS 的远程推送通知?的主要内容,如果未能解决你的问题,请参考以下文章

iOS推送通知和远程通知的区别?

iOS开发 - ANPs推送通知 标签: 推送通知ANPs远程推送本地推送

iOS(本地通知与远程通知)

Swift - GCM:不显示 iOS 远程推送通知

远程推送通知

在Objective C(iOS)中向远程推送通知添加消息