悬而未决的问题,旨在了解我认为可能很常见的问题的最佳实践或最常见的解决方案。
假设我有一个要下载的 URL 列表;该列表本身托管在服务器上,因此我启动了一个下载它的 NSURLConnection。connectionDidFinishLoading 中的代码将使用 URL 列表为每个 URL 异步实例化一个新的 NSURLConnection;这反过来将触发更多的 NSURLConnections,依此类推 - 直到没有更多的 URL。将其视为连接树。
检测所有连接何时完成的最佳方法是什么?
我将问题指向iOS7,但欢迎对其他版本发表评论。
几个想法:
-
在从服务器检索列表后触发后续下载方面,只需将执行这些后续下载的逻辑放在第一个请求的完成处理程序块(或完成委托方法)中即可。
-
在下载一堆文件方面,如果面向iOS 7及更高版本,则可以考虑使用
NSURLSession
而不是NSURLConnection
。- 首先,通过启动"下载"
任务(而不是"数据"任务)来下载具有适度内存占用的文件。
其次,您可以使用 后台
NSURLSessionConfiguration
,即使用户离开应用程序,也可以继续下载。请参阅适用于 iOS 的应用程序编程指南的在后台下载内容部分。如果你这样做,有很多 i 需要点和 t 需要交叉,但这是一个值得考虑实现的很棒的功能。
请参阅 WWDC 2013 基础网络中的新增功能,了解
NSURLSession
简介。或者参阅 URL 加载系统编程指南的相关章节。 -
在跟踪你是否完成方面,正如Wain所建议的那样,你可以只跟踪发出的请求数和完成/失败的请求数,在你的"任务完成"逻辑中,只需比较这两个数字,如果完成数与请求数匹配,则启动"全部完成"逻辑。有很多方法可以做到这一点,在某种程度上取决于你的实现细节,但希望这说明了基本思想。
GCD,不如考虑使用 NSOperationQueue
。您还应该将并发操作的数量(当然是在移动设备上)限制为 4 个,这样您就不会用请求淹没网络。
现在,队列上的操作数是剩余计数。您可以在每个操作的末尾添加一个块,以检查队列计数并执行任何完成逻辑。
正如 Rob 在他的回答中所说,你可能要考虑 NSURLSession,而不是自己做这件事。它具有许多优点。
其他选项是构建自己的下载管理器类,或使用现成的第三方框架,如AFNetworking。我只使用过AFNetworking一点点,但从我所看到的它优雅,强大且易于使用
。我们公司为一个早于AFNetworking和NSURLSession的项目编写了一个基于NSURLConnection的异步下载管理器类。这并不难,但它不像NSURLSession或AFNetworking那样灵活。