我如何知道何时可以安全地重用来自另一个进程的后台 NSURLSessionConfiguration id?

Posted

技术标签:

【中文标题】我如何知道何时可以安全地重用来自另一个进程的后台 NSURLSessionConfiguration id?【英文标题】:How can I know when it's safe to reuse a background NSURLSessionConfiguration id from another process? 【发布时间】:2016-06-30 08:02:27 【问题描述】:

我正在构建一个应用程序,用户可以在其中启动应用程序和共享扩展的后台文件上传。用户应该能够监控从主应用上传的任何进度。

在从扩展程序启动上传的情况下,我需要创建一个后台会话配置,其 ID 与扩展程序中使用的相同,以获取委托调用以监控应用程序中的进度等。

在应用程序中,我无法在扩展程序退出之前执行此操作。 苹果文档说https://developer.apple.com/library/prerelease/content/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html

您必须为每个标识符创建一个会话(当您指定 创建配置对象)。多个会话的行为 共享相同的标识符是未定义的。

我已经验证了这一点。如果我不关闭共享扩展,我可以在主应用程序中创建会话而不会出现任何错误,但我不会收到任何委托呼叫。 当我在切换回主应用程序之前关闭扩展程序时,我可以附加到同一个后台会话并收到委托呼叫。都很好。

当我在NSExtensionContext 中使用completeRequestReturningItems:completionHandler: 关闭共享扩展时,进程何时退出?

https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSExtensionContext_Class/#//apple_ref/occ/instm/NSExtensionContext/completeRequestReturningItems:completionHandler:

提及

调用此方法最终会关闭应用扩展的视图 控制器。

“最终”不是很具体。我如何从主应用中确定扩展程序没有运行?

我想出的唯一解决方法是定期在共享容器中写入一个文件,并让主 upp 在超时时间超过该时间段后首先获取后台会话。但这是一个丑陋的 hack。

如果上传量很小,是否有可能在扩展程序运行时完成上传,所以我必须在扩展程序中而不是在主应用程序中处理上传的完成?

总结一下:如何安全地将上传内容从应用扩展传输到应用?

【问题讨论】:

【参考方案1】:

Quinn“爱斯基摩人!”对这类问题进行了精彩的讨论。 on the old Dev Forums here.

与你直接相关的部分是

在我的测试中,我注意到这种设计中出现了一些烦人的行为:如果您从扩展程序启动任务,则应用程序或扩展程序是否获得 didCompleteWithError 回调是不确定的。如果任务运行得非常快,扩展通常会收到回调。如果任务花费的时间更长,系统有时间终止扩展,并恢复应用程序来处理它。

真的没有办法解决这个问题。解决方法是将处理请求完成的代码放在您的应用和扩展程序中(可能通过框架重用代码)。

如果扩展程序可以在开始请求时立即断开会话,那就太好了。唉,这目前是不可能的(rdar://problem/18748008)。以编程方式断开会话的唯一方法是使其无效,并且取消所有正在运行的任务 (-invalidateAndCancel) 或等待它们完成 (-finishTasksAndInvalidate),这两种方法都不合适。

太好了,

是否有可能在扩展进程运行时上传完成,所以我必须在扩展中处理上传的完成

是的。是的。你不喜欢“不确定”的行为吗?

如何安全地将上传内容从应用扩展传输到应用?

当然听起来你不能。所以在那里欺骗雷达,然后耐心等待修复!

【讨论】:

这似乎(不幸的是:))是正确的答案。我必须实现通过共享容器中的文件的消息传递和心跳机制,我每秒左右更新一个文件,以了解何时可以安全地移交会话。

以上是关于我如何知道何时可以安全地重用来自另一个进程的后台 NSURLSessionConfiguration id?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中安全地实现可重用的暂存存储器?

node.js 进程如何知道何时停止?

安全地杀死在 bash 脚本中启动的后台进程

如何知道大 O 何时是对数?

与另一个单独的进程共享来自交换链后台缓冲区的 direct3d11 渲染帧作为纹理

在后台无限期地运行应用程序进程