因此,我一直在阅读远程通知,并最终使其正常工作;我们的应用程序正在接收来自我们服务器的通知。如果某个条件在我们的服务器上满足(例如通知不再有效),我们现在希望删除或更新未读通知。我明白“无声”通知是唯一的办法,但我仍然不知道如何去做。如果一个无声通知触发我的应用程序唤醒,我将能够安排本地通知,但我是否能够删除已经存在的远程通知?
唯一的解决方案是独占地使用来自服务器的无声通知,并将所有通知调度为具有自定义标识符的本地通知,我稍后可以删除这些通知?例如,如果我需要这个功能,我可以永远不使用fire&忘记从服务器到设备的远程推送通知吗?
编辑:此应用程序支持iOS 9 :/
发布于 2017-12-07 12:49:21
最后,我按照TawaNicolas在his answer中建议的那样做了,通过使用getDeliveredNoti....
获取接收到的通知,然后检查每个通知的userInfo,以找到我想要删除的通知。我将可移动通知的标识符存储在数组中,并称为removeDelivered...
。
这正是他的回答所暗示的,但一开始并没有奏效,我很难找到原因。我仍然不能完全确定我是否修复了它,但是我的测试表明它是有效的--我的解决方案有点道理。
问题是,在didReceiveRemote..
-function中,你必须在最后调用completionHandler(.newData)
。这是为了通知NotificationCenter某些事情发生了变化。我开始怀疑这个回调是在可移动通知被实际删除之前调用的。我检查了文档,removeDeliveredNotifications
确实是异步的。这意味着当我这样做时:
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: removableIDs)
completionHandler(.newData)
不保证在调用第二个函数之前完成了第一个函数。这意味着completionHandler
(它告诉我的NotificationCenter某些内容已经更新)首先完成,然后从系统中删除通知。(NotificationCenter显然不调用自己的completionHandler来更新该函数之后的UI )。
所有这些都可能发生,也可能不会发生。正如我所经历的那样;当连接到调试器时,removeDeliveredNotifications
-function是如此之快,以至于它总是在调用completionHandler
之前完成,这意味着在更新系统之前删除了通知。因此,在开发这个项目时,一切看起来都很棒。当我断开与调试器的连接时,removeDeliveredNotifications
-function稍微慢一些,而且由于它是异步的,所以它是在我调用completionHandler
之后完成的--导致系统更新得太快。
解决这一问题的最好方法是苹果给我们一个completionBlock removeDeliveredNotifications
,并在它里面调用我们的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之后,总是在我删除通知之后执行该延迟,而且它似乎每次都正常工作,不管是否连接了调试器。
这是个令人作呕的问题,有个肮脏的解决办法。
发布于 2017-10-11 13:31:14
应用程序从无声通知中醒来后,需要使用以下方法循环处理接收到的通知:
目标-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])
其中identifier
是notification.request.identifier
属性。
编辑:如果您想要标识正确的通知,您必须找出您在userInfo
中的有效负载中发送了哪些内容,可以识别正确的通知。(可能是userID还是eventID?这取决于您的项目。)
发布于 2017-10-11 13:36:53
对于iOS >= 10,可以使用UNUserNotificationCenter.current().getDeliveredNotifications
和/或UNUserNotificationCenter.current().removeAllDeliveredNotifications
您还必须添加import UserNotifications
,这是一个很好的新通知框架。
https://stackoverflow.com/questions/46689396
复制相似问题