0

I want to pull some data from server in every 30 min interval and set local notification to remind the user and i implemented below code to perform this operation.

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


    [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
    return YES;
}

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
    NSString *value = [[NSUserDefaults standardUserDefaults]objectForKey:@"bgFetch"];

    if ([Utilities isInternetConnectionAvailable]) {
        if ([self.window.rootViewController isKindOfClass:[HomeViewController class]]){

            HomeViewController *homeController = (HomeViewController*)self.window.rootViewController;
            [homeController fetchDatawithCompletionHandler:^(UserData *userData, NSString *errorResponse) {
                if (userData) {
                    if (![homeController isNotificationAvailvableForTheData:userData]) {
                        [homeController scheduleLocalNotificationForUserData:userData];
                        completionHandler(UIBackgroundFetchResultNewData);
                    }
                }else{
                    completionHandler(UIBackgroundFetchResultFailed);
                }
            }];
        }else{
            completionHandler(UIBackgroundFetchResultNoData);
        }

    }else{
        completionHandler(UIBackgroundFetchResultFailed);
    }
}

I also enabled background fetch in capability and added the key "Required background modes" in plist. When i checked after few hours, no local notification is set. Where am i doing wrong ?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
myCmyL
  • 435
  • 2
  • 4
  • 11
  • 1
    Maybe your `isInternetConnectionAvailable` is false, maybe your root view controller isn't a `HomeViewController`, maybe your notification code is wrong, maybe...maybe...maybe... :-) Have you tried to debug the issue? Hint: with Xcode you can simulate a background fetch using Debug > Simulate Background Fetch – Krumelur Feb 21 '18 at 19:14
  • You can use the debug menu in Xcode to force trigger a background refresh to test your code. It can take up to a day or even longer for iOS to start triggering background refresh calls. It is far more efficient to use push notifications than to rely on frequent background refresh polling, if possible. And finally, as @Krumelur says, you can't be sure that your home view controller exists if your app is launched in the background – Paulw11 Feb 21 '18 at 19:15
  • Yes. It works when i simulated background fetch using xcode simulator. But not on physical device. Device was connected to internet and homeviewcontroller is set as root view. I tested notification code snippet separately. – myCmyL Feb 21 '18 at 19:17
  • Put some debug output in your app and see how far that gets you. Make sure your app was running and put to background by pressing the home button of the device. Don't terminate the app or background fetch won't work. Also if your app crashes it won't get scheduled again. – Krumelur Feb 21 '18 at 19:23
  • Thank you @Krumelur. Will background fetch not work if app is terminated or not running ? – myCmyL Feb 22 '18 at 06:20
  • "In most cases, the system does not relaunch apps after they are force quit by the user. " See: https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html#//apple_ref/doc/uid/TP40007072-CH4-SW7 – Krumelur Feb 22 '18 at 08:03

1 Answers1

0

I was facing the same issue. Whenever I simulated a background fetch via XCode it worked, whether with the emulator or a real device. If I unplugged the phone and just used it as I usually do. I never got a notification, respectively my code doesn't get executed. The solution is very simple and I think the difference to "simulate background fetch" is that your app is in a different stage then it is in your daily routine. To make it work, simply dispatch your code on a background thread. I just wrapped my code inside:

DispatchQueue.global(qos: .background).async

and it worked.

Mark Kowalski
  • 264
  • 2
  • 9