0

I am trying to implement APNs in my app with the content-available key so that a background refresh will be triggered. Here is my code:

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

    if([userInfo[@"aps"][@"content-available"] intValue]== 1){

        //This stops a refresh happening is a push is delivered with the app in the foreground
        if(application.applicationState!=UIApplicationStateActive){

            NSLog(@“Background push refresh called");
            [self backgroundRefreshWithPushUpdate:NO andHandler:^(BOOL successful, BOOL newMessages) {

                if(successful){


                    if(newMessages) handler(UIBackgroundFetchResultNewData);
                    else handler(UIBackgroundFetchResultNoData);


                }

                else{

                    handler(UIBackgroundFetchResultFailed);

                }


            }];



        }

        else handler(UIBackgroundFetchResultNoData);

    }


}

I have this additional condition: if(application.applicationState!=UIApplicationStateActive) for refreshing in the background as I don't want it to be triggered if the app is in the foreground. However, if I receive a push and then tap on the notification to open the app ALL of the code in - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler is called again. This means my background fetch is called when the notification first comes in and then it's called again when the notification is tapped on. I don't want this to happen. Any ideas how I can get around this?

Kex
  • 8,023
  • 9
  • 56
  • 129

1 Answers1

2

Here are the things to be noticed in application:didReceiveRemoteNotification:fetchCompletionHandler: method when you receive a push notification:
1. When the app is not launched (i.e, when the app is neither in background nor in foreground), the method is called once and applicationState will be UIApplicationStateInactive.
2. When the app is in foreground, the method is called once and applicationState will be UIApplicationStateActive.
3. When the app is in background, the method is called twice, once when you receive the push notification, and other time when you tap on that notification. When you receive the push notification, applicationState will be UIApplicationStateBackground and when you tap on that notification, applicationState will be UIApplicationStateInactive.

We can ignore it when the applicationState will be UIApplicationStateBackground and hence we can handle the push notification only once for all the three scenarios.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    if (application.applicationState == UIApplicationStateBackground) {
        completionHandler(UIBackgroundFetchResultNoData);
        return;
    }

    // Do whatever you need here and call completionHandler with appropriate UIBackgroundFetchResult
}
Ganesh Kamath
  • 1,181
  • 11
  • 20
  • Got that in the end. Was a while ago now. Should of added an answer. thanks for this though. Will be useful for others. :) – Kex Nov 19 '15 at 11:24
  • Welcome Kex. Thanks for accepting my answer. Even I faced the same problem recently. I couldn't find the proper answer here and hence thought of printing out applicationState in different situations inside the method. This is how I arrived at this solution. Added this answer so that it will be helpful to others. :) – Ganesh Kamath Nov 19 '15 at 12:01