我知道有很多次问过类似的问题。但在阅读这些主题之后,我仍然非常困惑,特别是在iOS 10中引入UNUserNotificationCenter
之后。
官方文档提到了我可以处理远程通知的3种方法:
userNotificationCenter:willPresentNotification:withCompletionHandler:
来处理通知。userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:
。application:didReceiveRemoteNotification:fetchCompletionHandler:
方法。所以,
并且,更令人困惑的是:如果应用程序处于后台,则何时调用委托方法:何时收到通知消息?或者当用户点击通知时?
iOS 10及更高版本:
1)userNotificationCenter将发布通知:通常用于决定当用户已经进入应用程序并且通知到达时该怎么做。您可以在应用程序内触发远程通知。在他点击远程通知后,调用方法2(didReceive响应)。
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (_ options: UNNotificationPresentationOptions) -> Void) {
//Handle push from foreground
//When a notification arrives and your user is using the app, you can maybe notify user by showing a remote notification by doing this
completionHandler([.alert, .badge, .sound])
//To print notification payload:
print(notification.request.content.userInfo)
}
2)userNotificationCenter didReceive响应:通常用于在用户点击通知后将用户重定向到应用的特定屏幕。
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
//Handle push from background or closed (or even in foreground)
//This method is called when user taps on a notification
//To print notification payload:
print(response.notification.request.content.userInfo)
}
在iOS 10下面:
3)应用程序didReceiveRemoteNotification:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
//To print notification payload
print(userInfo)
if #available(iOS 10.0, *) {
}
else {
//Handle remote notifications for devices below iOS 10
if application.applicationState == .active {
//app is currently in foreground
}
else if application.applicationState == .background {
//app is in background
}
else if application.applicationState == .inactive {
//app is transitioning from background to foreground (user taps notification)
}
}
}
4)应用程序didFinishLaunchingWithOptions launchOptions:iOS 10以下设备的唯一场景是关闭app并且用户点击启动应用程序的通知。您必须为此方案检查以下方法。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//To print notification payload:
if let notification = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] as? [AnyHashable: Any] {
print(notification)
}
}
LaunchOptions是一个字典,指示应用程序启动的原因(如果有)。在用户直接启动应用程序的情况下,此词典的内容可能为空。
现在回答你的问题,
1)要在应用程序处于后台/非活动状态时处理远程通知,您必须在方法2(userNotificationCenter didReceive响应)中为iOS 10及更高版本的设备添加代码。此外,您必须为iOS 10以下的设备使用方法3(应用程序didReceiveRemoteNotification)。
2)要在iOS 10之前的应用程序在前台运行时处理远程通知,请使用方法3活动状态。
除了Ameya的出色答案之外,我还想指出,如果app处于背景状态,userNotificationCenter:willPresent:notification
就不会被调用。
我在iOS 10+上处理所有案例的完整解决方案是使用application:didFinishLaunchingWithOptions:launchOptions
,并检查是否处于后台状态,并在那里处理通知。但是,您的有效负载现在还需要包含"content-available": 1
字段。