如何清除 iOS 的远程推送通知?
How to clear a remote pushed notification for iOS?
所以我一直在研究远程通知,并最终使它起作用;我们的应用程序正在从我们的服务器接收通知。如果我们的服务器满足特定条件(例如,通知不再有效),我们现在想要删除或更新未读通知。我知道 "silent" 通知是唯一的方法,但我仍然对如何做感到困惑。
如果静默通知触发我的应用程序唤醒,我将能够安排本地通知,但我是否能够删除已经存在的远程通知?
唯一的解决方案是专门使用来自服务器的静默通知,并将 所有 通知安排为带有我稍后可以删除的自定义标识符的本地通知吗?
例如,如果我想要此功能,我可以永远不使用从我的服务器到设备的 fire&forget 远程推送通知吗?
编辑:此应用最多支持 iOS 9 :/
在您的应用从静默通知中唤醒后,您需要使用以下方法循环接收通知:
Objective-C:
[[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
}];
Swift:
UNUserNotificationCenter.current().getDeliveredNotifications { (notifications: [UNNotification]) in
}
然后检查每个通知的 request.content.userInfo
属性 以确定是否是您要删除的通知。
然后,您使用以下方法将其从通知中心删除:
Objective-C:
[[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:@[identifier]];
Swift:
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [identifier])
其中 identifier
是 notification.request.identifier
属性。
编辑:如果你想识别正确的通知,你必须找出你在 userInfo
中的有效载荷中发送的内容,可以识别正确的通知。 (可能是 userID 还是 eventID?这取决于您的项目。)
对于 iOS >= 10 你可以使用 UNUserNotificationCenter.current().getDeliveredNotifications
and/or UNUserNotificationCenter.current().removeAllDeliveredNotifications
您还必须添加 import UserNotifications
,这是一个不错的新通知框架。
我最终按照 TawaNicolas 在 中建议的那样做了,通过使用 getDeliveredNoti....
获取收到的通知,然后检查每个通知的 userInfo 以找到我想删除的通知。我将可移动通知的标识符存储在一个数组中,并调用 removeDelivered...
.
这与他的回答所暗示的完全一样,但这一开始并没有奏效,我很难找出原因。我仍然不完全确定我已经修复了它,但我的测试表明它正在工作 - 我的解决方案有些道理。
问题是,在 didReceiveRemote..
函数中,您必须在最后调用 completionHandler(.newData)
。这是为了通知 NotificationCenter 某些内容已更改。我开始怀疑这个回调是在 之前 可移动通知实际上被删除之前调用的。我查看了文档, removeDeliveredNotifications
确实是异步的。这意味着当我这样做时:
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: removableIDs)
completionHandler(.newData)
不保证第一个函数在调用第二个函数之前完成。这意味着通知我的 NotificationCenter 某些内容已更新的 completionHandler
首先完成,然后通知从系统中删除。 (NotificationCenter 显然不会在该函数之后调用自己的 completionHandler 来更新 UI)。
这一切可能会也可能不会发生。正如我所经历的那样;当连接到调试器时,removeDeliveredNotifications
函数速度如此之快,以至于它总是在调用 completionHandler
之前完成,这意味着在更新系统之前删除了通知。所以在开发这个时一切看起来都很棒。当我与调试器断开连接时,removeDeliveredNotifications
-函数稍微慢一些,并且由于它是异步的,所以它在 我调用 completionHandler
之后完成 - 导致系统更新太快了。
解决这个问题的最佳方法是 Apple 为我们提供 removeDeliveredNotifications
的 completionBlock 并在其中调用我们的 completionHandler
,但他们没有。
现在为了解决这个问题,我添加了 0.2 秒的固定延迟。它可能低于 0.2,但对于我们正在做的事情来说,它并不重要。
这是我创建的一个 class 函数,可以轻松地从任何地方延迟某些东西:
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:
in AppDelegate
:
中使用它
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: removableIDs)
RuntimeUtils.delay(seconds: 0.2, closure: {
completionHandler(.newData)
})
将此延迟添加到 completionHandler 后,它总是在我删除通知后执行,而且似乎每次都有效,无论是否连接调试器。
这是一个恶心的问题,有一个令人讨厌的修复。
所以我一直在研究远程通知,并最终使它起作用;我们的应用程序正在从我们的服务器接收通知。如果我们的服务器满足特定条件(例如,通知不再有效),我们现在想要删除或更新未读通知。我知道 "silent" 通知是唯一的方法,但我仍然对如何做感到困惑。 如果静默通知触发我的应用程序唤醒,我将能够安排本地通知,但我是否能够删除已经存在的远程通知?
唯一的解决方案是专门使用来自服务器的静默通知,并将 所有 通知安排为带有我稍后可以删除的自定义标识符的本地通知吗? 例如,如果我想要此功能,我可以永远不使用从我的服务器到设备的 fire&forget 远程推送通知吗?
编辑:此应用最多支持 iOS 9 :/
在您的应用从静默通知中唤醒后,您需要使用以下方法循环接收通知:
Objective-C:
[[UNUserNotificationCenter currentNotificationCenter] getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> * _Nonnull notifications) {
}];
Swift:
UNUserNotificationCenter.current().getDeliveredNotifications { (notifications: [UNNotification]) in
}
然后检查每个通知的 request.content.userInfo
属性 以确定是否是您要删除的通知。
然后,您使用以下方法将其从通知中心删除:
Objective-C:
[[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers:@[identifier]];
Swift:
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [identifier])
其中 identifier
是 notification.request.identifier
属性。
编辑:如果你想识别正确的通知,你必须找出你在 userInfo
中的有效载荷中发送的内容,可以识别正确的通知。 (可能是 userID 还是 eventID?这取决于您的项目。)
对于 iOS >= 10 你可以使用 UNUserNotificationCenter.current().getDeliveredNotifications
and/or UNUserNotificationCenter.current().removeAllDeliveredNotifications
您还必须添加 import UserNotifications
,这是一个不错的新通知框架。
我最终按照 TawaNicolas 在 getDeliveredNoti....
获取收到的通知,然后检查每个通知的 userInfo 以找到我想删除的通知。我将可移动通知的标识符存储在一个数组中,并调用 removeDelivered...
.
这与他的回答所暗示的完全一样,但这一开始并没有奏效,我很难找出原因。我仍然不完全确定我已经修复了它,但我的测试表明它正在工作 - 我的解决方案有些道理。
问题是,在 didReceiveRemote..
函数中,您必须在最后调用 completionHandler(.newData)
。这是为了通知 NotificationCenter 某些内容已更改。我开始怀疑这个回调是在 之前 可移动通知实际上被删除之前调用的。我查看了文档, removeDeliveredNotifications
确实是异步的。这意味着当我这样做时:
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: removableIDs)
completionHandler(.newData)
不保证第一个函数在调用第二个函数之前完成。这意味着通知我的 NotificationCenter 某些内容已更新的 completionHandler
首先完成,然后通知从系统中删除。 (NotificationCenter 显然不会在该函数之后调用自己的 completionHandler 来更新 UI)。
这一切可能会也可能不会发生。正如我所经历的那样;当连接到调试器时,removeDeliveredNotifications
函数速度如此之快,以至于它总是在调用 completionHandler
之前完成,这意味着在更新系统之前删除了通知。所以在开发这个时一切看起来都很棒。当我与调试器断开连接时,removeDeliveredNotifications
-函数稍微慢一些,并且由于它是异步的,所以它在 我调用 completionHandler
之后完成 - 导致系统更新太快了。
解决这个问题的最佳方法是 Apple 为我们提供 removeDeliveredNotifications
的 completionBlock 并在其中调用我们的 completionHandler
,但他们没有。
现在为了解决这个问题,我添加了 0.2 秒的固定延迟。它可能低于 0.2,但对于我们正在做的事情来说,它并不重要。
这是我创建的一个 class 函数,可以轻松地从任何地方延迟某些东西:
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:
in AppDelegate
:
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: removableIDs)
RuntimeUtils.delay(seconds: 0.2, closure: {
completionHandler(.newData)
})
将此延迟添加到 completionHandler 后,它总是在我删除通知后执行,而且似乎每次都有效,无论是否连接调试器。
这是一个恶心的问题,有一个令人讨厌的修复。