警告:应用程序委托收到对-application的调用:performFetchWithCompletionHandler:但是从未调用完成处理程序

时间:2017-07-22 09:33:30

标签: ios delphi background-fetch

我实施performFetchWithCompletionHandler(即:后台获取)从服务器下载一些数据。

要做到这一点,在performFetchWithCompletionHandler内,为了不阻止主线程,我创建并启动一个新任务(所以在后台线程中),当任务完成时我拨打CompletionHandler

给出的performFetchWithCompletionHandler

但无论如何,只要performFetchWithCompletionHandler被调用,我就会在日志中(以及下载任务完成之前)立即收到

  

警告:应用程序代表收到了来电   -application:performFetchWithCompletionHandler:但是从未调用完成处理程序。

所以我无法理解怎么办?这是否意味着所有工作必须在程序performFetchWithCompletionHandler 内完成(所以在主线程中)并且performFetchWithCompletionHandler必须仅在所有工作完成时返回,阻止这种方式主线程?

请帮助我了解如何正确使用

这是我的代码(它在delphi中,但它完全按照我之前所描述的,没有我用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 个答案:

答案 0 :(得分:0)

- (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.");
    }];
}