MatterGoal
MatterGoal

Reputation: 16430

Using NSURLSession to download a lot of images

I have created a simple testing app to learn how to use NSURLSession. This App has to download images from a webservice and present them into a UITableView. I've already written the first part of the App that reads a list of images urls from the web service, now, I want to display this list.

My doubt is:

given that the list of images could be a really long list, is it ok to create a NSURLSessionDownloadTask for each image? I thought to create the session in the cellForRowAtIndexPath function and store the NSURLSessions in a NSDictionary using as key the IndexPath of the cell (and probably relying on NSURLCache to avoid to download the same images more than once).

Other solutions:

I can see three more solutions:

  1. Using GCD with dispatch_async

  2. Subclassing NSOperation and essentially store an NSOperation for any image I need to download.

  3. Using a third party library like AFNetwork... but since it is a learning purpose app I prefer to go completely with my code .

If the multiple NSURLSession isn't a good solution, I'd choose one of those options.

What do you think about this approach?

Upvotes: 2

Views: 1797

Answers (4)

E. Rivera
E. Rivera

Reputation: 10938

I would use (or at least take a look at) SDWebImage's SDWebImageManager.

Besides downloading you can set priority and continue in the background options which I think you'll want to have.

Upvotes: 1

quellish
quellish

Reputation: 21254

NSURLSessionTask is fine for a large number of downloads. One advantage of it over some of the other methods you mentioned is that downloads can be cancelled or paused. It also correctly implements concurrency for network operations, which is more difficult than many cats on the internet will lead you to believe (if you don't believe me, view the eskimo's 2010 WWDC session and sample code. NSOperation for network connections is not trivial).

NSURLSessionTask and friends are designed for exactly the kinds of problems you are trying to solve, and it's very well tested.

For a tableview, start the task in tableView:willDisplayCell:forRowAtIndexPath: and cancel (or pause) a task in tableView:didEndDisplayingCell:forRowAtIndexPath:. That will limit the active downloads to the currently visible cells.

Upvotes: 6

Sadiq Jaffer
Sadiq Jaffer

Reputation: 500

IMO whilst it is ok to create an NSURLSessionTask for each image a standard first in first out implementation will cause problems when scrolling through your cells. The reason for this is that downloads will be queued on your NSURLSession and tasks will be executed in the order they've been added to the queue, in other words in a FIFO manner. Imagine a scenario where you've scrolled through a vast number of cells and you have to wait for all downloads to complete in order. You would not only have to wait a long time, you would be making unnecessary network requests for image assets that may no longer be relevant to your user.

Nick Lockwood created a great NSOperationQueue subclass called NSOperationStack that reverses the order of operations so that the the last operation is executed first (LIFO). IMO for a large number of downloads a LIFO implementation is a must.

NSOsperationStack is available here

If you combine this with an implementation that uses cellForRowAtIndexPath to initiate and NSURLCache to store downloads, you should end up with a very streamlined and efficient solution.

Upvotes: 1

Midhun MP
Midhun MP

Reputation: 107231

Suggestion:

I also came across a similar situation were I need to download about 2000 Image files and 100 Video files. For that purpose I implemented a custom download manager using NSOperationQueue and blocks.

I have added this library to GitHub, please feel free to check the implementation.

Upvotes: 3

Related Questions