我实施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;
答案 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.");
}];
}