didReceiveRemoteNotification被调用两次。

8

我已经在我的应用程序中实现了推送通知。

当我的应用程序在前台运行时,它可以正常工作。

但是当应用程序在后台或被杀死时,didReceiveRemoteNotification 会被调用两次。

我创建了一个公共方法来处理推送通知,并从 didFinishLaunchingWithOptionsdidReceiveRemoteNotification 中调用此方法。

这是我的实现:

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

  NSDictionary *pushDictionary = [launchOptions valueForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
  if (pushDictionary) {
    [self customPushHandler:pushDictionary];
  }

  return YES;

}

而且:

- (void)application:(UIApplication *)application
   didReceiveRemoteNotification:(NSDictionary *)userInfo
  fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {


         [self customPushHandler:userInfo];

 }

AND:

 - (void) customPushHandler:(NSDictionary *)notification {

     // Code to push ViewController

         NSLog(@"Push Notification"); //Got it two times when Clicked in notification banner

   }

当我的应用程序正在运行时,视图控制器会被推送一次。当我从通知横幅打开我的应用程序时,我的屏幕会被推送两次。

我在customPushHandler中放置了一个NSLog,当应用程序在前台运行时,我得到了一次日志记录,当我从通知横幅启动它时,我得到了两次日志记录。

我的代码有什么问题?


1
请参考以下链接:https://dev59.com/QmEh5IYBdhLWcg3wvFjY#6LvmnYgBc1ULPQZFi3LK - Avijit Nagare
4个回答

6

"当应用程序在后台运行时,该方法会调用两次,一次是在接收到推送通知时,另一次是当您点击通知时。"

您可以验证应用程序的状态,并在应用程序处于后台时忽略接收到的通知。

解决方案: 远程通知方法调用两次

Swift 4代码:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

        if (application.applicationState == .background) {
            completionHandler(.noData)
            return
        }

    // logic
    // call completionHandler with appropriate UIBackgroundFetchResult
}

0
didReceiveRemoteNotification 中检查这个条件,例如 如果你在应用程序在后台时点击通知。通过这种方式,您可以避免被调用两次。
 - (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
      UIApplicationState state = [[UIApplication sharedApplication] applicationState];
      if (state == UIApplicationStateBackground || state == UIApplicationStateInactive || state == UIApplicationStateForeground || state == UIApplicationStateActive)
      {
          //Do checking here.
          [self customPushHandler:userInfo];
      }
}

请检查我已经编辑了我的回答。


不要在条件语句中调用此方法。因为如果应用程序从后台打开,则应调用此方法。如果应用程序被终止,则应该从didfinishlauch方法中调用您的处理程序。 - RJV Kumar
你没有理解我的意思。我在didFinishLaunchingWithOptions中也调用了customPushHandler方法。如果我使用你的代码,那么我的customPushHandler将会被调用两次,并且当我的应用程序在前台时,customPushHandler将永远不会被调用。 - Rahul
应用程序不会同时调用这两种方法。它们具有文档所描述的不同功能。因此,可以使用(pushDictionary)检查,如if(pushDictionary!= nil)。或在两个方法中记录pushDictionary。如果您得到相同的值或nil? - RJV Kumar

0

检查当前导航栏中的顶部视图控制器,如下:

if(![self.navigationController.topViewController isKindOfClass:[MyClass class]]) {

           //code for pushing new controller

 }

0
无论何时使用backgroundFetch进行远程通知,都要添加一个完成处理程序。
- (void)application:(UIApplication *)application
   didReceiveRemoteNotification:(NSDictionary *)userInfo
   fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {

    [self customPushHandler:userInfo];

    completionHandler(UIBackgroundFetchResultNewData)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接