应用程序终止时处理推送通知

Handling Push Notifications when App is Terminated

当我的应用程序不是 运行 并收到推送通知时,如果我单击该通知,应用程序将启动 - 但它不会使用我设置的警报视图提示用户,询问他们是否要查看通知的内容。它刚刚启动,并坐在那里。

当应用程序处于 运行 时,推送通知可以完美运行 - 无论是作为活动应用程序还是在后台 - 但当应用程序不是 运行.[=10 时,推送通知无法正常工作=]

我尝试注销应用程序中的 launchOptions NSDictionary:didFinishLaunchingWithOptions: 以查看其带来的负载 - 但它显示为“(null)”。所以它基本上什么都不包含 - 这没有意义,因为它不应该包含通知的负载吗?

有人知道如何在应用程序未 运行 时让推送通知正常工作吗?

我的意思是当应用程序处于非 运行 状态时如何处理推送通知。如果,如果您收到很多通知并且您没有打开应用程序,您也没有点击系统的通知面板怎么办?您如何保留这些推送以供以后检索。

根据您的问题,当您打开应用程序时无法保留所有通知,最好您调用 api 以根据时间戳从您的后台获取所有通知 end/server Facebook 就是这样做的。

该应用程序不会在后台处理推送通知,它真正做的 OS 是在您按下通知后唤醒该应用程序。您可以通过以下方式捕捉这一刻:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    { 

        if ([launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey]) {
      // Your app has been awoken by a notification...
        }
   }

1) 当应用程序在后台运行时当应用程序运行 ] 在前景中 application:didReceiveRemoteNotification: 方法将如下调用。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    if (application.applicationState == UIApplicationStateInactive)
    {
        // opened from a push notification when the app was on background
        NSLog(@"userInfo->%@", [userInfo objectForKey:@"aps"]);
    }
    else if(application.applicationState == UIApplicationStateActive)
    {
        // a push notification when the app is running. So that you can display an alert and push in any view
        NSLog(@"userInfo->%@", [userInfo objectForKey:@"aps"]);
    }
}

2) 当应用程序未启动时(关闭) 然后 application:didFinishedLaunchingWithOptions 方法将被调用。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    if (launchOptions != nil)
    {
        // opened from a push notification when the app is closed
        NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
        if (userInfo != nil)
        {
             NSLog(@"userInfo->%@", [userInfo objectForKey:@"aps"]);
        }
    }
    else
    {
        // opened app without a push notification.
    }
}

3) 目前无法删除特定通知。从您的应用程序中删除所有通知以便当用户从其中一个应用程序打开应用程序时它们不会显示在通知中心的方法是将应用程序徽章设置为 0。

应用程序端无法处理此问题。 您需要在服务器上维护未读徽章计数。 当应用程序被终止时,徽章值将从服务器更新。

因此,当您随时打开应用程序时,您需要调用网络服务来获取所需的通知并更新标签栏的徽章(如果使用)。

您可以使用 getDeliveredNotifications(completionHandler:) 方法检索发送到您的应用程序的通知。请注意,这仅 returns 当前显示在通知中心的通知,而不是用户手动清除的通知。

UNUserNotificationCenter.current().getDeliveredNotifications { notifications in

    // notifications: An array of UNNotification objects representing the local
    // and remote notifications of your app that have been delivered and are still
    // visible in Notification Center. If none of your app’s notifications are
    // visible in Notification Center, the array is empty.

    // As said in the documentation, this closure may be executed in a background
    // thread, so if you want to update your UI you'll need to do the following:
    DispatchQueue.main.sync { /* or .async {} */ 
        // update UI
    }
}

您可以在启动之前终止的应用后通过如下通知显示提醒:

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { // display the alert }

在终止状态下收到通知后执行操作 - iOS 13 - 场景委托

最近我遇到了一个问题,当我的应用程序处于终止状态时,我收到了远程推送通知。在最新的 iOS 版本中,Scene delegate 负责处理视图生命周期方法,而不是 App Delegate。

旧 iOS 版本 - 由 App Delegate 处理 当应用程序终止并收到远程推送通知时,负载会反映在应用程序委托的 didfinishLaunchingWithOptions 方法中。使用此方法的启动参数,可以获取有效负载数据并执行任何交互。

新 iOS 版本 - 由场景代表处理 同样,当应用程序终止并收到远程推送通知时,有效负载反映在场景委托的场景(willConnectTo 会话)中。使用此方法的 connectingOption 参数可以获取有效负载数据并执行任何交互。

提示:一旦视图控制器被设置为根视图控制器,要执行任何交互或将此有效负载传递给另一个视图控制器,请保持几秒钟的延迟来传递数据。

示例代码:

guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
 
if defaults.string(forKey: UserDefaultsKeys.TenantID.rawValue) != nil && connectionOptions.notificationResponse != nil {
   
  let rootViewController = UINavigationController(rootViewController: DashboardVC())
  window?.rootViewController = rootViewController
  window?.makeKeyAndVisible()
   
  DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
    NotificationCenter.default.post(
      name: .passApnsDataToDashboardNotification,
      object: nil,
      userInfo: connectionOptions.notificationResponse?.notification.request.content.userInfo)
  }
   
}