0

I am working on an app where I need to download lots of images locally (so that they are available offline). The number of images can be 100 - 10,000. Each image may vary from 100K- 250K

I can do this via a NSOperationQueue and I have the code to make this work already but this question is more of a conceptual nature. I am not sure what is the best approach to take here.

1) Do I download all images as soon as the user logs in for the first time ? Based on the number of images, this could take a long time and what if the user closes the app meanwhile. I understand there is a limit on the time that can be spent by a background process in this case? Honestly, I dont want to do anything in the background (ie when app is closed)

2) Do I download images when a particular category is selected by the user? If a category has 800 images, then what happens if the user selects another category before all of those 800 images are finished downloading? I can always start threaded downloaded but will the thread keep on running if the user selects another category ?

3) Put something in "Settings" to let the user decide this themselves. Something like "Total Images: 8000" Images Available : 2000 and a button to say "Download All" which would display a UIProgressView of what's going on....so the user will probably wait till it's all done.

Or some other approach?

Thoughts?

Anuj Gakhar
  • 681
  • 2
  • 13
  • 26
  • What kind of app is this? If the images are part of the app, then just bundle it with the app. If the images are user generated content or some content that you serve, then you have to think whether you need all the images at once or not - usually not I think. – nhahtdh Jun 20 '12 at 15:57
  • This is user generated content so can not be bundled with the app. – Anuj Gakhar Jun 20 '12 at 16:02
  • You can do progressive loading (display a fixed number, only load more when user requests), and/or create a thumbnail for all the images, so that you only load the full image when user wants to see in detail. Another way is to show a loading screen where you download everything locally for the first time, but this may take long if there are too many images, and user may ragequit if they have to wait too long. – nhahtdh Jun 20 '12 at 16:04
  • I generate thumbnails locally and download the large image from the server. Which is why the option of downloading just the thumbnails is not there. This is a Photo management app. Lots of images in lots of different categories. There is a thumbnail grid view of each Category and selecting a photo shows a FullScreen view. Much like the "Photos" App. – Anuj Gakhar Jun 20 '12 at 16:07
  • if the images are static per category, why not download them as a gzip (+1 for the thumbnail comment)? then unpack once everything is in, let the user select what he needs. You basically have one trip to the server, with option for resume. The IO for handling each request seperate will take some extra time and burden on your server. – Roger Jun 20 '12 at 21:00
  • @Rogier That;s quite an interesting idea. The only overhead is to generate these zip files on the server (as the images change every now and then). But if the zip files are there, this could mean just one round trip to the server and all the images are in, in one go. I like that. – Anuj Gakhar Jun 21 '12 at 07:41
  • Yeah, i would make a MD5 hash. So you could even check if the zip changed easily. My experience is you want to limit the amount of roundtrips to the servers, its a huge penalty you pay in terms of performance. Especially if you also have concurrent users using it. And you don't want to fix that (penalty) by scaling up your h/w. GL! – Roger Jun 21 '12 at 08:05

2 Answers2

0

I would only download the image when the user actually needs to do something with the image. Your users will hate you if you download all the images upfront. :)

tjg184
  • 4,508
  • 1
  • 27
  • 54
  • That normally works but I am trying to make everything available offline. And following this approach, only the images that have been viewed atleast once, be available offline. – Anuj Gakhar Jun 20 '12 at 16:03
  • Can you download the ones actively being worked on, mark them as downloaded, and then only download new ones that need to be worked with? There is a timeout when the app is pushed to the background. You can request more time, but it's generally around 10 minutes. – tjg184 Jun 20 '12 at 16:05
  • So eventually (not all at once), all the images will be downloaded, but only when needed. – tjg184 Jun 20 '12 at 16:06
  • Yep, I've got this far already actually. Progressive download and once downloaded, it's not downloaded again unless server says the image is updated. But again, this means the user has to browse the app, each category, scroll through to the end for each category (my code downloads images as and when they are needed in the Grid Scroll View)...but again, this is bad as the user has a task of clicking through and scrolling a lot on the app before its available offline. – Anuj Gakhar Jun 20 '12 at 16:10
0

As far as I understand from your description, including comments, I think that the best approach would be downloading all of your images in a thread and make the download process resumable. In this way, you are going to mirror a remote database of images for offline use.

What this entails is:

  1. you keep track of which images you have downloaded;

  2. each time the app starts/resumes, you start the downloading thread exactly from where you left;

  3. you should also provide a mechanism so that the user is suitably informed when he is trying to access an image which has not been downloaded yet, but I think this should be no problem (you might also provide a progress indicator somewhere).

sergio
  • 68,819
  • 11
  • 102
  • 123
  • That's exactly what I am trying to accomplish. Mirror a remote database of images for offline use. However, I am not sure how to make a thread resumable. I have all the images in a Core Data Entity so I know exactly which ones have been downloaded and which ones are not. Have you got any code to show how to start/resume a process? – Anuj Gakhar Jun 20 '12 at 16:14
  • it is the download that must be resumable, not the thread; each time you start a new thread and this thread will download the remaining pictures. does this help? – sergio Jun 20 '12 at 16:22
  • Yes. So this thread would be in the following AppDelegate method? - (void)applicationDidBecomeActive:(UIApplication *)application – Anuj Gakhar Jun 20 '12 at 16:26
  • that's a good place IMO... and don't forget to shut it down properly in `applicationWillEnterForeground` (stop the queue, I mean, and make your data persistent). – sergio Jun 20 '12 at 16:29
  • I assume you meant `applicationWillResignActive` ? – Anuj Gakhar Jun 20 '12 at 16:34
  • OK, so start a thread with NSOperationQueue in `applicationDidBecomeActive` and stop the queue in `applicationWillResignActive`. And each time query the Core data for non-downloaded images and start downloading them. I think that's pretty cool as it does not depend on the user clicking anywhere on the app and because OperationQueue is pretty fast, the images would be there soon enough I guess. I'll try it out. Thanks. – Anuj Gakhar Jun 20 '12 at 16:38
  • Hi sergio, I have a related question here http://stackoverflow.com/questions/11175855/afnetworking-nsoperationqueue-download-thousands-of-images - see if you can help out. thanks a lot. – Anuj Gakhar Jun 24 '12 at 07:50