【发布时间】:2017-07-22 09:33:29
【问题描述】:
我实现了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;
【问题讨论】:
-
你能给我们看看代码吗?
-
有点难给大家看,因为它是用delphi写的,恐怕你看不懂,但过程和我说的一模一样。 performFetchWithCompletionHandler => 创建一个后台任务 => 当任务完成调用completionHandler
-
你不必担心阻塞
performFetchWithCompletionHandler中的主线程,因为你不在前台;但是,如果您在没有调用completionHandler的情况下从该函数返回,则必须在返回之前调用beginBackgroundTaskWithExpirationHandler,并在调用完成处理程序后调用endBackgroundTask -
@Paulw11 :谢谢,您能否再澄清一点(我认为您甚至可以将其作为有用的答案)。在 performFetchWithCompletionHandler 内部的主线程中做所有事情是正常的做法(即:要走的路)吗?我知道应用程序不在前台,但如果任务需要 30 秒才能完成,而在中间用户想要将应用程序置于前台怎么办?另一方面,在 performFetchWithCompletionHandler 中使用 beginBackgroundTaskWithExpirationHandler 看起来更像是一个 hack
-
问题是你在没有调用完成处理程序的情况下从函数返回并且iOS不知道你还有一个后台任务在运行;这就是为什么你需要打电话给
beginBackgroundTaskWithExpirationHandler
标签: ios delphi background-fetch