如何使用 AFNetworking 2.x 管理许多 (>500) 后台 URLSession 下载?

Posted

技术标签:

【中文标题】如何使用 AFNetworking 2.x 管理许多 (>500) 后台 URLSession 下载?【英文标题】:How to manage many (>500) background URLSession downloads with AFNetworking 2.x? 【发布时间】:2015-07-23 19:15:37 【问题描述】:

我在应用商店有一个应用,它使用 AFNetworking 2.x 在后台通过基于 NSURLSession 的下载来下载大文件,因为用户通常会将应用置于后台(当然它会在一段时间后终止,但下载完成都是一样的。太棒了)。这个应用程序运行良好。通常用户一次只下载几个文件。

现在我需要制作另一个类似的应用程序,但这一次不是几个大文件,而是用户很可能想要下载大量小文件:例如,500 个 1-5mb 的文件每个。同样,该应用程序通常会被置于后台,所以我想继续使用 NSURLSessionDownloadTask,除非有很好的理由不这样做。

我的问题是,我可以一次简单地创建 500 个 NSURLSessionDownloadTasks 吗? AFNetworking 是否会进行一些巧妙的节流以避免系统过载?还是ios做到了?或者什么都不做,我不得不痛苦地跟踪和组织我的应用程序重新启动时的传输状态(即,因为它被置于后台最终终止)?

如果有人知道您可以同时可靠地创建多少个 NSURLSessionDownloadTasks 的限制,那就太棒了... 谢谢!

附言我非常喜欢 obj-c 到 swift,谢谢 :)

【问题讨论】:

将此问题发布到 Apple 内部网络论坛 - 您将得到明确的答案。 在你的服务器上用选定的文件制作一个 .zip 并在内部处理它不是可能的吗? @BenjaminJimenez 服务器不是我的 @DavidH 我不确定你的意思,苹果内部论坛在哪里?对不起,如果这是一个愚蠢的问题 @xaphod forums.developer.apple.com/community/core-os/networking 【参考方案1】:

上次我检查过(还没有查看 iOS 9 测试版),任务创建出乎意料地昂贵且超线性。在我的测试运行中:

50 个任务 -> ~1.5s 200 个任务 -> ~11.5s 500 个任务 -> ~55s

由于我的文件数量通常是 5 位数,因此一次安排所有内容对我来说不是一个解决方案。我的方法(尚未投入生产,我停止开发该功能以支持其他事情)将持久性与NSURLSessionDownloadTask 结合起来,并使用会话标识符来分类特定文件属于哪个逻辑下载。根据我是处于正常生命周期还是来自-application:handleEventsForBackgroundURLSession:completionHandler:(调试这种情况可能会很痛苦;NSUserDefaults 是你的朋友),将安排一位代表进一步下载。这个理论似乎很合理,我可以看到任务确实被安排了,但我目前无法让 iOS 下载程序守护进程符合我的意愿。

如果您可以选择 Benjamin Jimenez 建议的服务器端 zip,请帮自己一个忙,改用它。

【讨论】:

感谢 Kyo,这很有帮助。因此,如果我理解正确,您会预先安排一些任务,然后当它们完成时,您会安排更多。使用这种方法,您是否发现可以在您的应用程序处于后台时安排额外的 NSURLSessionDownloadTasks(即通过handleEventsForBackgroundURLSession)?其他陷阱是什么(即守护程序不符合您的意愿)?可悲的是,在这种情况下,服务器端 zip 是不可能的。我担心的是用户必须一次又一次地打开应用程序,甚至只是为了开始传输。布莱克... 这就是它的要点。即使我的应用程序刚刚由 iOS 启动以处理事件,我也可以从后台进行安排。 iOS 为您提供了大约 30 秒的时间来执行此操作,如果您届时不调用提供的完成处理程序,砰!守护进程的问题(从后台调度的任务运行时间过长)可能会或可能不会通过调整会话配置来缓解。另一个陷阱是所有跟踪都必须手动完成,以及一些在后台启动时可能不成立的常见假设(在我的例子中,CoreData 在“主线程”上放置了一个私有队列上下文)。 在启动应用程序以处理事件时,您所要做的就是会话标识符和 source URL,因此无论您拥有什么结构都需要能够构建上下文仅此而已。在你调用完成处理程序的那一刻,iOS 让应用程序进入睡眠状态,如果你使用了很多 dispatch_async(),这是需要注意的。 谢谢京。是的,我熟悉通过会话标识符和源 URL 重建状态......你能告诉我更多关于“从后台安排的任务需要很长时间才能运行”吗?你的意思是你可以从后台安排任务,但是当你通过resume启动它们时,它们要等很长时间才能真正启动?任务最终启动是否至少可靠,或者用户有时必须打开应用程序才能启动它?谢谢! 自从我被要求处理更紧急的功能以来,我没有对这个问题进行广泛调查,但据我所见,任务已创建,我在它们上调用 -resume。如果我没记错的话,任务确实会开始,有时会在几个小时后开始,并且它们实际上可能会失败,具体取决于会话超时的设置方式。在实践中,我最终打开了应用程序以再次下载。我认为如果我使用小超时,iOS 会快点运行我的任务,但似乎并非如此。今晚我会尝试运行一个干净的测试。【参考方案2】:

苹果开发者论坛上的苹果员工“爱斯基摩人”帮我找到了答案,你可以在这个论坛帖子中看到:

https://forums.developer.apple.com/thread/11621

在此处粘贴相关部分:

(我)我已经阅读了这个帖子和你在这里链接到的那个 (https://devforums.apple.com/message/938057#938057) 我有一个 关于通过以下方式下载 10,000-20,000 个文件的最佳做法的问题 NSURLSessionDownloadTasks。 (免责声明,我使用的是 AFNetworking 2.x)。 我的目标是 iOS 8 和更新版本,所以答案不必在 iOS 上工作 7. 我们如何计算合理的批次(组)大小?我了解恢复速率限制器意味着希望批量大小更高, 但同时任务请求的最大限制未知 会使守护进程崩溃。

(me) 我的假设是当用户打开我的应用程序并运行时 在前台一段时间,然后速率限制器“重置”或 类似——所以现在事情会再次顺利进行。这是假设吗 对吗?

(爱斯基摩人)是的。此外,从 iOS 8 开始,如果用户带来了您的应用 到前面然后iOS会自动给任务一个“踢”。我有 忘记了这个的确切机制,但我很确定它被覆盖了 在WWDC 2014 Session 707 What's New in Foundation Networking。

【讨论】:

以上是关于如何使用 AFNetworking 2.x 管理许多 (>500) 后台 URLSession 下载?的主要内容,如果未能解决你的问题,请参考以下文章

AFNetworking 2.x JSON POST 数据在服务器上为空

在 AFNetworking 2.x 中设置自定义标头后,RESTful API 未接收到参数

AFNetworking 2.x 带有 xml 正文的 POST 请求

在故障块 AFNetworking 3.0 上获取 responseObject

如何查看 AFNetworking 的 Swift API?

如何从 AFNetworking 禁用缓存