26

根据苹果指南:

“作为呈现通知的结果,用户点击警报的操作按钮或点击(或点击)应用程序图标。如果点击操作按钮(在运行 iOS 的设备上),系统将启动应用程序和应用程序调用其委托的 application:didFinishLaunchingWithOptions: 方法(如果已实现);它传入通知负载(用于远程通知)或本地通知对象(用于本地通知)。

如果在运行 iOS 的设备上点击应用程序图标,应用程序会调用相同的方法,但不会提供有关通知的信息。如果在运行 Mac OS X 的计算机上单击应用程序图标,应用程序将调用委托的 applicationDidFinishLaunching: 方法,委托可以在该方法中获取远程通知负载。”

我的问题是假设用户从提供者那里收到了 3-4 条推送通知,并且全部都存储在苹果的通知中心。如果用户点击通知警报,他/她可以轻松地在应用程序中获取通知数据。但是如果用户点击 iPhone 上的应用程序图标,如何获取与所有先前通知相关的所有数据。

提前致谢!

4

5 回答 5

40

您不能,您只会收到有关用于打开您的应用程序的通知的信息。

因此,如果用户打开您的应用,并且您的应用有通知,您将无法从应用中检索它们。

一种解决方法可能是跟踪服务器上的通知并在应用程序中处理它。因此,服务器跟踪已读取的通知。这就是 Facebook 的做法。

于 2012-07-02T09:11:35.067 回答
16

要以正确的方式做到这一点,必须满足一些条件:

您的服务器知道您的应用当前看到了什么以及它可以再次发送哪些通知。

让我们只考虑远程通知。应用程序的三种状态:

  • 前景

    • 通知在没有用户操作的情况下出现:

      func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
          //handle your notification
      }
      

    您可以使用第三方库显示横幅:BSForegroundNotification

  • 背景

    • 通知出现在屏幕上。(请注意,在推送通知中设置 content-available=1 可能会导致在按下应用程序图标后显示最新的推送消息,因为调用了 didReceive...

      //nothing is called in the app, but app icon badge changes
      // OR - if the notification contains the field content-available set to 1 - 
      func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
          //handle your notification
      } 
      
    • 用户点击通知

      func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
          //handle your notification
      }           
      
    • 用户采取通知操作

      func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
           //handle your notification's action
      }
      

      或者

      func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], withResponseInfo responseInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
           //handle your notification's action response info
      }
      
    • 用户点击应用程序图标

      func applicationDidBecomeActive(application: UIApplication) {
          //fetch pending notifications from server
      }
      
  • 根本没有运行

    • 通知出现在屏幕上。

      //nothing is called in the app, but app icon badge changes
      
    • 用户点击通知

      func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
          if let userInfo = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? [NSObject: AnyObject] {
              //handle your notification
          }
      }
      
    • 用户采取通知操作

      func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
           //handle your notification's action
      }
      

      或者

      func application(application: UIApplication, handleActionWithIdentifier identifier: String?, forRemoteNotification userInfo: [NSObject : AnyObject], withResponseInfo responseInfo: [NSObject : AnyObject], completionHandler: () -> Void) {
           //handle your notification's action response info
      }
      
    • 用户点击应用程序图标

      func applicationDidBecomeActive(application: UIApplication) {
          //fetch pending notifications from server
      }
      

如何处理通知?

  1. let notification = WLNotification(userInfo: userInfo)

    当您收到通知时,请记住WLNotification保持当前应用程序状态。将来您可能需要它知道该通知的来源。

  2. WLNetworkClient.sharedClient().notificationForIdentifier(notification.identifier)

    从服务器获取有关该通知的详细信息,同时让它知道您确实收到了该通知,并影响了用户的数据。

如何获取所有待处理的通知?

WLNetworkClient.sharedClient().pendingNotificationsWithCompletionBlock(nil)

获取您错过的所有通知。换句话说,获取那些未在服务器中标记为您已接收的那些。

阅读Apple 推送通知的限制

查看相关问题:

于 2015-09-26T09:27:47.130 回答
3

我遇到了同样的问题:如果用户点击推送横幅,他会获得推送应用程序的信息,如果他点击应用程序图标,他不会得到它。您可以从它处理衍生一,但只有一些限制。例如,如果您想从推送中获得徽章编号,您可以这样做:(推送 -> 应用程序图标 -> 应用程序图标徽章 -> 您的 var)

在 AppDelegate

- (void)applicationWillEnterForeground:(UIApplication *)application
{ 
    newMessages = application.applicationIconBadgeNumber;
}
于 2015-03-03T16:18:37.133 回答
1

从概念上讲,当应用程序通过单击为推送通知呈现的警报视图加载时,didReceiveLocalNotification如果您的应用程序在后台,则应用程序将使用委托方法启动。此时applicationDidFinishLaunching委托方法没有被调用。

当您的应用程序不在后台时,单击为推送通知显示的警报视图将调用applicationDidFinishLaunching方法。

希望这可以清除您对这两种委托方法之间的理解。

于 2012-07-02T09:12:06.210 回答
-2

您可以使用以下代码:

 NSArray *pendingNotifications = [[[UIApplication sharedApplication] scheduledLocalNotifications] sortedArrayUsingComparator:^(id obj1, id obj2)                       {

        if ([obj1 isKindOfClass:[UILocalNotification class]] && [obj2 isKindOfClass:[UILocalNotification class]])
        {
            UILocalNotification *notif1 = (UILocalNotification *)obj1;
            UILocalNotification *notif2 = (UILocalNotification *)obj2;
            return [notif1.fireDate compare:notif2.fireDate];
        }

        return NSOrderedSame;
 }];

 // if there are any pending notifications -> adjust their badge number
 if (pendingNotifications.count != 0)
 {
     //do something
 }
于 2014-08-27T17:38:53.880 回答