为啥 userNotificationCenter didReceive 没有被解雇?
Posted
技术标签:
【中文标题】为啥 userNotificationCenter didReceive 没有被解雇?【英文标题】:Why userNotificationCenter didReceive is not fired?为什么 userNotificationCenter didReceive 没有被解雇? 【发布时间】:2018-11-24 16:44:18 【问题描述】:这是我的代码的一部分。我想使用UNUserNotificationCenter
和UNUserNotificationCenterDelegate
来处理通知事件。
此代码在应用处于前台状态时捕获通知事件。但是"didReceive"
不会因为后台状态而被触发。
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool
UNUserNotificationCenter.current().delegate = self
application.registerForRemoteNotifications()
return true
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
print("willPresent") /// This works
completionHandler([.alert, .badge, .sound])
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void)
print("didReceive") /// This doesn't work
completionHandler()
但如果我不使用UNUserNotificationCenter.current().delegate = self
,委托方法会在后台正确触发。
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping FetchCompletionHandler)
print("didReceiveRemoteNotification... \(userInfo)")
如何使用“didReceive”?我想在后台处理通知。
【问题讨论】:
【参考方案1】:application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
在应用程序接收到静默推送通知时被调用。当应用程序处于后台状态时,可以发送静默推送通知,ios 唤醒应用程序执行用户不可见的后台处理。
静默推送通知将 content-available
标志设置为 1。
静默推送通知不应包含警报、徽章或声音。静默推送并不意味着对用户可见,它只是向应用程序提示新的远程内容可用。
从推送通知负载中删除content-available
标志将导致iOS 将其作为常规通知处理。将调用用户通知中心委托方法而不是 application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
,但您的应用程序将无法执行通知触发的后台处理。
您可以使用this tool 验证推送通知负载的内容是否存在此类问题
【讨论】:
这似乎不是这种情况(不再):“要支持后台更新通知,请确保有效负载的 aps 字典包含值为 1 的内容可用键。如果有是与后台更新一起出现的用户可见更新,您可以根据需要在 aps 字典中设置警报、声音或徽章键。”来自developer.apple.com/library/archive/documentation/…【参考方案2】:这就是我在应用程序中处理推送通知的方式。我认为您需要实现所有这些方法以在前台和后台模式下处理所有 iOS 版本。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
if #available(iOS 10.0, *)
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: [.sound,.alert,.badge], completionHandler: (granted, error) in
if error == nil
DispatchQueue.main.async
application.registerForRemoteNotifications()
)
else
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)
application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
let deviceTokenString = deviceToken.reduce("", $0 + String(format: "%02X", $1))
print(deviceTokenString)
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error)
print("Failed to get token; error: \(error)")
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
completionHandler([.alert,.sound])
//do sth
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void)
//do sth
// for iOS < 10
func application(_ application: UIApplication, didReceive notification: UILocalNotification)
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
【讨论】:
【参考方案3】:有UNUserNotificationCenterDelegate的方法:
willPresent:当您的应用处于前台时,当您收到通知时会调用此方法。如果应用程序在后台,则此方法不会调用。
didRecieve:当用户点击通知时调用此方法。
在后台状态下,当用户点击通知时,只会调用“didRecieve”。
【讨论】:
以上是关于为啥 userNotificationCenter didReceive 没有被解雇?的主要内容,如果未能解决你的问题,请参考以下文章
选择通知操作时不会调用 userNotificationCenter(_:didReceive:withCompletionHandler:)
从 userNotificationCenter 检索通知类型:didReceiveNotificationResponse:withCompletionHandler:
userNotificationCenter didReceive 响应包含空通知(watchOS)
iOS 将通知对象发送到 UserNotificationCenter 和 didFinishLaunchingWithOptions