46

In Xcode 7.0.1 the "simulate background" fetch command causes performFetchWithCompletionHandler to be triggered twice.

Is this an Xcode debugging error, or can this happen on a device running a release build of the application.

Update Now we have Xcode 7.1.1 and still performFetchWithCompletionHandler is called twice. Since I am not sure if this also happens "in the wild" I am keeping a state if my fetch action is already running.

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler {
    if (self.performingFetch) {
        return completionHandler(UIBackgroundFetchResultNoData);
    }
    self.performingFetch = YES;
    ...
    self.performingFetch = NO;
}
MarkHim
  • 5,322
  • 5
  • 28
  • 61
  • 1
    I'm experiencing the same thing (regardless of whether `[application setMinimumBackgroundFetchInterval:]` is called during launch). – Graham Oct 14 '15 at 15:05
  • 1
    Any updates on this? I also experience the same thing. – Marcel Gruber Oct 23 '15 at 01:22
  • 1
    same thing here. xcode 7 and ios 9 – Rashid Oct 28 '15 at 14:43
  • 1
    Another "me too". Seems to be an iOS 9 bug, because also happens with Xcode 6.4 on iOS 9, doesn't happen with Xcode 7 on iOS 8.4. – ernesto Nov 02 '15 at 11:04
  • same here. @MarcHim: I tried with maintaining a state as well. I though suspect that the second call, that hits the state that Fetch already in progress and triggers completionHandler also completes for the first call that is still processing code. Can this be? (my code, which downloads and NSXML parses an RSS feed, never seems to get executed with background fetch on physical device. And this would be an explanation...) – TPeter Nov 16 '15 at 12:48
  • 2
    I think this is an iOS 9 bug. Also I can confirm it also happens "in the wild" – Cloud9999Strife Dec 07 '15 at 04:59

1 Answers1

1

I got around this issue by declaring a static boolean in the App Delegate, and then using the boolean to get the background fetch to perform once

if (!runOnce)
{
    [submission startSubmissionProcessWithCompletetionHandler:^(UIBackgroundFetchResult result){
        NSDate *fetchStart = [NSDate date];

        completionHandler(result);

        NSDate *fetchEnd = [NSDate date];
        NSTimeInterval timeElapsed = [fetchEnd timeIntervalSinceDate:fetchStart];
        NSLog(@"Background Fetch Duration: %f seconds", timeElapsed);
    }];
    runOnce = YES;
}
else
{
    completionHandler(UIBackgroundFetchResultNoData);
    runOnce = NO;
}