I am working on building a download manager functionality for the app I am working on. As a requirement we need to support maximum of three parallel downloads. I saw some code examples of this forum using same delegate object and create multiple instances of NSURLConnection objects. A drawback (that I think, and I may be wrong) to this approach is, all the callbacks to delegate object would happen on the same thread. This would result in packets being queued up on the thread. Am I missing something here.
Is there any other way of implementing this functionality such as do a NSInvocationQueue and start individual download on a different thread and thus get better efficiency. With this approach it adds a lot of complexity for tracking progress for each download, pause/resume downloads an开发者_JAVA技巧d thread management.
I am planning to create asynchronous requests on individual thread and not keep synchronous connections for obvious reasons. Also I am downloading large video files > 100 MB and storing it directly to a file. I am a little unclear as to how packets would be queued up and would I run out or memory or would it make main thread unresponsive.
Any pointers or help is greatly appreciated.
Thanks
As Tommy has pointed out, using separate threads just for downloading data is generally not very efficient. It also has a higher memory overhead than using the asynchronous interface of NSURLConnection
on the main thread and you lose a lot of control (you can't cancel synchronous connections running on a background thread).
You're right, the delegate callbacks will all be queued on the main thread, but usually, the only thing you do there is to concatenate the data chunks until your download is finished – this is computationally very cheap.
If you intend to do computationally expensive things with the data after it's downloaded (like creating thumbnail images, parsing etc.), you could easily dispatch that work to a GCD queue after your connection has finished downloading. That way, you don't lose control over the download process, can easily display progress or cancel running downloads, but still don't block the main thread.
Apple's recommendation is that you use NSURLConnection asynchronously with a delegate rather than using threads and a blocking connection. If you use multiple NSURLConnections on the same thread then the data will all be returned on the same thread, but that isn't a problem. The data doesn't somehow become intertwined unless your code intertwines it, and there will be no effect on network performance.
Launching threads simply for the process of fetching data is less efficient, especially in battery utilisation, than simply using multiple NSURLConnections on the same thread.
It will help - http://allseeing-i.com/ASIHTTPRequest/
For parallel download you can use ASINetworkQueue.
You shall look into HTTP Client library like ASIHTTPRequest.
ASIHTTPRequest handle concurrent requests using a queue, which you can limit the concurrency easily. Example code borrowed from ASIHttpRequest:
- (IBAction)grabURLInTheBackground:(id)sender
{
if (![self queue]) {
[self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
}
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request setDidFinishSelector:@selector(requestDone:)];
[request setDidFailSelector:@selector(requestWentWrong:)];
[[self queue] addOperation:request]; //queue is an NSOperationQueue
}
- (void)requestDone:(ASIHTTPRequest *)request
{
NSString *response = [request responseString];
}
- (void)requestWentWrong:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
Modify the [NSOperationQueue maxConcurrentOperationCount] to change concurrency.
精彩评论