this is an open question aiming at understanding what is the best practice or the most common solution for a problem that I think might be common.
这是一个悬而未决的问题,旨在了解什么是我认为可能常见的问题的最佳实践或最常见的解决方案。
Let's say I have a list of URLs to download; the list is itself hosted on a server, so I start a NSURLConnection that downloads it. The code in connectionDidFinishLoading will use the list of URLs to instantiate one new NSURLConnection, asynchronously, per each URL; this in turn will trigger even more NSURLConnections, and so on - until there are no more URLs. See it as a tree of connections.
假设我有一个要下载的URL列表;列表本身托管在服务器上,因此我启动了一个NSURLConnection来下载它。 connectionDidFinishLoading中的代码将使用URL列表为每个URL异步实例化一个新的NSURLConnection;这反过来会触发更多的NSURLConnections,依此类推 - 直到没有更多的URL。将其视为连接树。
What is the best way to detect when all connections have finished?
检测所有连接何时完成的最佳方法是什么?
I'm aiming the question to iOS7, but comments about other versions are welcome.
我的目标是iOS7,但欢迎其他版本的评论。
3 个解决方案
#1
4
A couple of thoughts:
几点想法:
-
In terms of triggering the subsequent downloads after you retrieve the list from the server, just put the logic to perform those subsequent downloads inside the completion handler block (or completion delegate method) of the first request.
在从服务器检索列表后触发后续下载方面,只需将逻辑放在第一个请求的完成处理程序块(或完成委托方法)中执行后续下载。
-
In terms of downloading a bunch of files, if targeting iOS 7 and later, you might consider using
NSURLSession
instead ofNSURLConnection
.在下载一堆文件方面,如果定位iOS 7及更高版本,您可以考虑使用NSURLSession而不是NSURLConnection。
-
First, the downloading of files with a nice modest memory footprint is enabled by initiating "download" tasks (rather than "data" tasks).
首先,通过启动“下载”任务(而不是“数据”任务)来启用具有良好适度内存占用的文件的下载。
-
Second, you can do the downloads using a background
NSURLSessionConfiguration
, which will let the downloads continue even if the user leaves the app. See the Downloading Content in the Background section of the App Programming Guide for iOS. There are a lot of i's that need dotting and t's that need crossing if you do this, but it's a great feature to consider implementing.其次,您可以使用后台NSURLSessionConfiguration进行下载,即使用户离开应用程序也可以继续下载。请参阅适用于iOS的应用程序编程指南的背景部分中的下载内容。如果你这样做,有很多我需要点和t需要交叉,但这是一个很好的功能,考虑实施。
See WWDC 2013 What's New in Foundation Networking for an introduction to
NSURLSession
. Or see the relevent chapter of the URL Loading System Programming Guide.有关NSURLSession的介绍,请参阅WWDC 2013 Foundation Foundation中的新功能。或者参阅URL加载系统编程指南的相关章节。
-
-
In terms of keeping track of whether you're done, as Wain suggests, you can just keep track of the number of requests issued and the number of requests completed/failed, and in your "task completion" logic, just compare these two numbers, and initiate the "all done" logic if the number of completions matches the number of requests. There are a bunch of ways of doing this, somewhat dependent upon the details of your implementation, but hopefully this illustrates the basic idea.
在跟踪你是否已经完成时,正如Wain建议的那样,你可以只跟踪发出的请求数量和完成/失败的请求数量,在“任务完成”逻辑中,只需比较这两个数字,如果完成次数与请求数匹配,则启动“全部完成”逻辑。有很多方法可以做到这一点,在某种程度上取决于您的实现细节,但希望这说明了基本的想法。
#2
2
Instead of using GCD you should consider using NSOperationQueue
. You should also limit the number of concurrent operations, certainly on mobile devices, to perhaps 4 so you don't flood the network with requests.
您应该考虑使用NSOperationQueue而不是使用GCD。您还应该将并发操作的数量(当然在移动设备上)限制为4,这样您就不会使网络充满请求。
Now, the number of operations on the queue is the remaining count. You can add a block to the end of each operation to check the queue count and execute any completion logic.
现在,队列上的操作数是剩余计数。您可以在每个操作结束时添加一个块以检查队列计数并执行任何完成逻辑。
#3
1
As Rob says in his answer you might want to consider NSURLSession rather than doing this yourself. It has a number of advantages.
正如Rob在他的回答中所说,你可能想要考虑NSURLSession而不是自己这样做。它有许多优点。
Other options are building your own download manager class, or using a ready-made third party framework like AFNetworking. I've only worked with AFNetworking a little bit but from what I've seen its elegant, powerful, and easy to use.
其他选项是构建自己的下载管理器类,或使用现成的第三方框架,如AFNetworking。我只使用AFNetworking一点点,但从我看到它优雅,强大,易于使用。
Our company wrote an async download manager class based on NSURLConnection for a project that predates both AFNetworking and NSURLSession. It's not that hard, but it isn't as flexible as either NSURLSession or AFNetworking.
我们公司编写了一个基于NSURLConnection的异步下载管理器类,用于一个早于AFNetworking和NSURLSession的项目。它并不难,但它不像NSURLSession或AFNetworking那样灵活。
#1
4
A couple of thoughts:
几点想法:
-
In terms of triggering the subsequent downloads after you retrieve the list from the server, just put the logic to perform those subsequent downloads inside the completion handler block (or completion delegate method) of the first request.
在从服务器检索列表后触发后续下载方面,只需将逻辑放在第一个请求的完成处理程序块(或完成委托方法)中执行后续下载。
-
In terms of downloading a bunch of files, if targeting iOS 7 and later, you might consider using
NSURLSession
instead ofNSURLConnection
.在下载一堆文件方面,如果定位iOS 7及更高版本,您可以考虑使用NSURLSession而不是NSURLConnection。
-
First, the downloading of files with a nice modest memory footprint is enabled by initiating "download" tasks (rather than "data" tasks).
首先,通过启动“下载”任务(而不是“数据”任务)来启用具有良好适度内存占用的文件的下载。
-
Second, you can do the downloads using a background
NSURLSessionConfiguration
, which will let the downloads continue even if the user leaves the app. See the Downloading Content in the Background section of the App Programming Guide for iOS. There are a lot of i's that need dotting and t's that need crossing if you do this, but it's a great feature to consider implementing.其次,您可以使用后台NSURLSessionConfiguration进行下载,即使用户离开应用程序也可以继续下载。请参阅适用于iOS的应用程序编程指南的背景部分中的下载内容。如果你这样做,有很多我需要点和t需要交叉,但这是一个很好的功能,考虑实施。
See WWDC 2013 What's New in Foundation Networking for an introduction to
NSURLSession
. Or see the relevent chapter of the URL Loading System Programming Guide.有关NSURLSession的介绍,请参阅WWDC 2013 Foundation Foundation中的新功能。或者参阅URL加载系统编程指南的相关章节。
-
-
In terms of keeping track of whether you're done, as Wain suggests, you can just keep track of the number of requests issued and the number of requests completed/failed, and in your "task completion" logic, just compare these two numbers, and initiate the "all done" logic if the number of completions matches the number of requests. There are a bunch of ways of doing this, somewhat dependent upon the details of your implementation, but hopefully this illustrates the basic idea.
在跟踪你是否已经完成时,正如Wain建议的那样,你可以只跟踪发出的请求数量和完成/失败的请求数量,在“任务完成”逻辑中,只需比较这两个数字,如果完成次数与请求数匹配,则启动“全部完成”逻辑。有很多方法可以做到这一点,在某种程度上取决于您的实现细节,但希望这说明了基本的想法。
#2
2
Instead of using GCD you should consider using NSOperationQueue
. You should also limit the number of concurrent operations, certainly on mobile devices, to perhaps 4 so you don't flood the network with requests.
您应该考虑使用NSOperationQueue而不是使用GCD。您还应该将并发操作的数量(当然在移动设备上)限制为4,这样您就不会使网络充满请求。
Now, the number of operations on the queue is the remaining count. You can add a block to the end of each operation to check the queue count and execute any completion logic.
现在,队列上的操作数是剩余计数。您可以在每个操作结束时添加一个块以检查队列计数并执行任何完成逻辑。
#3
1
As Rob says in his answer you might want to consider NSURLSession rather than doing this yourself. It has a number of advantages.
正如Rob在他的回答中所说,你可能想要考虑NSURLSession而不是自己这样做。它有许多优点。
Other options are building your own download manager class, or using a ready-made third party framework like AFNetworking. I've only worked with AFNetworking a little bit but from what I've seen its elegant, powerful, and easy to use.
其他选项是构建自己的下载管理器类,或使用现成的第三方框架,如AFNetworking。我只使用AFNetworking一点点,但从我看到它优雅,强大,易于使用。
Our company wrote an async download manager class based on NSURLConnection for a project that predates both AFNetworking and NSURLSession. It's not that hard, but it isn't as flexible as either NSURLSession or AFNetworking.
我们公司编写了一个基于NSURLConnection的异步下载管理器类,用于一个早于AFNetworking和NSURLSession的项目。它并不难,但它不像NSURLSession或AFNetworking那样灵活。