Search code examples
iphoneiosobjective-cxcodeipad

Showing Accurate Progress In UIProgressView While Downloading Images in iphone


I have four urls which consists images... I'm downloding those images and placing them into documents folder..

here is my code..

-(void)viewDidLoad
{
NSMutableArray *myUrlsArray=[[NSMutableArray alloc]init];
[myUrlsArray addObject:@"http://blogs.sfweekly.com/thesnitch/steve_jobs3.jpg"];
[myUrlsArray addObject:@"http://www.droid-life.com/wp-content/uploads/2012/12/Steve-Jobs-Apple.jpg"];
[myUrlsArray addObject:@"http://2.bp.blogspot.com/-T6nbl0rQoME/To0X5FccuCI/AAAAAAAAEZQ/ipUU7JfEzTs/s1600/steve-jobs-in-time-magazine-front-cover.png"];
[myUrlsArray addObject:@"http://images.businessweek.com/ss/08/09/0929_most_influential/image/steve_jobs.jpg"];
[myUrlsArray addObject:@"http://cdn.ndtv.com/tech/gadget/image/steve-jobs-face.jpg"];

for (int i=0; i<myUrlsArray.count; i++)
{
    [self downloadImageFromURL:[myUrlsArray objectAtIndex:i] withName:[NSString stringWithFormat:@"MyImage%i.jpeg",i]];
}

}




#pragma mark- downloading File

-(void)downloadImageFromURL:(NSString *)myURLString withName:(NSString *)fileName
{
UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:myURLString]]];

NSLog(@"%f,%f",image.size.width,image.size.height);

   // Let's save the file into Document folder.**

    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];

NSString *jpegPath = [NSString stringWithFormat:@"%@/%@",documentsPath,fileName];// this path if you want save reference path in sqlite
NSData *data2 = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0f)];//1.0f = 100% quality
[data2 writeToFile:jpegPath atomically:YES];

}

NOW... I need to display a UIProgressView for above downloading progress accurately.

how can i achieve this functionality...

Can any one provide some guidelines to achieve this..

Thanks in advance...


Solution

  • I'd suggest you use some asynchronous downloading technique (either AFNetworking, SDWebImage, or roll your own with delegate-based NSURLSession) rather than dataWithContentsOfURL so that (a) you don't block the main queue; and (b) you can get progress updates as the downloads proceed.

    I'd also suggest creating a NSProgress for each download. When your delegate method gets updates about how many bytes have been downloaded, update the NSProgress object.

    You then can associate each NSProgress with a observedProgress for a UIProgressView, and when you update your NSProgress, the UI can be updated automatically.

    Or, if you and a single UIProgressView to show the aggregate progress of all of the NSProgress for each download, you can create a parent NSProgress, establish each download's NSProgress as a child of the parent NSProgress, and then, as each download updates its respective NSProgress, this will automatically trigger the calculation of the parent NSProgress. And again, you can tie that parent NSProgress to a master UIProgressView, and you'll automatically update the UI with the total progress, just by having each download update its individual NSProgress.


    There is a trick, though, insofar as some web services will not inform you of the number of bytes to be expected. They'll report an "expected number of bytes" of NSURLResponseUnknownLength, i.e. -1! (There are logical reasons why it does that which are probably beyond the scope of this question.) That obviously makes it hard to calculate what percentage has been downloaded.

    In that case, there are a few approaches:

    1. You can throw up your hands and just use an indeterminate progress indicator;

    2. You can try changing the request such that web service will report meaningful "expected number of bytes" values (e.g. https://stackoverflow.com/a/22352294/1271826); or

    3. You can use an "estimated download size" to estimate the percentage completion. For example, if you know your images are, on average, 100kb each, you can do something like the following to update the NSProgress associated with a particular download:

      if (totalBytesExpectedToWrite >= totalBytesWritten) {
          self.progress.totalUnitCount = totalBytesExpectedToWrite;
      } else {
          if (totalBytesWritten <= 0) {
              self.progress.totalUnitCount = kDefaultImageSize;
          } else {
              double written = (double)totalBytesWritten;
              double percent = tanh(written / (double)kDefaultImageSize);
              self.progress.totalUnitCount = written / percent;
          }
      }
      
      self.progress.completedUnitCount = totalBytesWritten;
      

      This is a bit of sleight of hand that uses the tanh function to return a "percent complete" value that smoothly and asymptotically approaches 100%, using the kDefaultImageSize as the basis for the estimation.

      It's not perfect, but it yields a pretty decent proxy for percent completion.