Warning: Application delegate received call to -application:performFetchWithCompletionHandler: but the completion handler was never called

Viewed 1660

I implement the performFetchWithCompletionHandler (ie: background fetch) to download some data from a server.

To do this, inside performFetchWithCompletionHandler, to not block the main thread, i create and start a new task (so in a background thread), and when the task is finished i call the CompletionHandler given with performFetchWithCompletionHandler

But no matter, as soon as the performFetchWithCompletionHandler is called i receive immediately in the log (and before the downloading task finish)

Warning: Application delegate received call to -application:performFetchWithCompletionHandler: but the completion handler was never called.

so i can't understand how to do ? does it's mean that all the job must be done inside the procedure performFetchWithCompletionHandler (so in the main thread) and performFetchWithCompletionHandler must return only when all the job is finished, blocking by this way the main thread ?

please help me to understand how to do correctly

This is my code (it's in delphi, but it's does exactly what i describe before without the network connection that i replace by sleep(15000) ) :

class procedure TMainForm.performFetchWithCompletionHandler(self: id; _cmd: SEL; application: PUIApplication; completionHandler: id);
begin

  aTaskID := SharedApplication.beginBackgroundTaskWithExpirationHandler(SynchLocationsTaskExpired);

  //load the Profiles in other thread to not block the calling thread
  fSynchLocationsTask := TThread.CreateAnonymousThread(
    procedure
    begin

      Sleep(15000);


      TThread.Queue(nil,
        procedure
        begin
          ExecutePerformFetchCompletionHandler(completionHandler, UIBackgroundFetchResultNewData); // ==> here the app crash like completionHandler is not valid anymore 
          SharedApplication.endBackgroundTask(aTaskID);  
        end);

    end);
  fSynchLocationsTask.FreeOnTerminate := False;
  fSynchLocationsTask.Start;

  // => here i receive in log Warning: Application delegate received call to -application:performFetchWithCompletionHandler: but the completion handler was never called

end;
1 Answers
- (void)application:(UIApplication*)application performFetchWithCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler {
    NSLog(@"Started background fetch");

    // Create URL session based on NSURLSession object which is required for all background fetch operations.
    MyUrlSession* urlSession = MyUrlSession.new;

    // Update is asynchronous so we have to tell to application that
    // we will call completion handler asynchronously. It prevents showing warning
    // that completion handler was never called.
    UIBackgroundTaskIdentifier backgroundTaskIdentifier = [application beginBackgroundTaskWithName:@"MyBgTask" expirationHandler:^{
        // This will cancel update and will call completion handler with error.
        NSLog(@"Expiration handler for background fetch");
        [urlSession cancel];
    }];

    // Start URL session with completion handler.
    [urlSession startWithCompletionHandler:^(BOOL successful, NSString *errorString) {
        NSLog(@"Background fetch completed with success = %d, error = %@", successful, errorString);
        [application endBackgroundTask:backgroundTaskIdentifier];
        completionHandler(successful ? UIBackgroundFetchResultNewData : UIBackgroundFetchResultFailed);
        NSLog(@"Background fetch has ended.");
    }];
}
Related