1

I want to download multiple images from URL to my device in iOS App.

//
//  ImageDownload.m
//

#import "ImageDownload.h"

@implementation ImageDownload {
    int *position;
    NSArray *downloableImages;
}

- (void)start:(NSArray *)images delegate:(id)delegate
{
    position = 0;
    downloableImages = images;

    NSUInteger *count = ((NSUInteger *)[downloableImages count]);
    NSLog(@"%d", count);

    [self startDownload];
}

- (void)startDownload
{
    NSUInteger *imageDataCount;

    NSArray *image;
    NSString *filename;
    NSString *fileurl;

    NSURLRequest *imageUrlRequest;

    image = [downloableImages objectAtIndex:position];

    NSLog(@"%d", position);

    NSArray *imageData = [image valueForKey:@"image"];
    imageDataCount = ((NSUInteger *)[imageData count]);

    if (imageDataCount > 0) {
        filename = [imageData objectAtIndex:0];
        fileurl = [imageData objectAtIndex:1];

        NSLog(@"%@", fileurl);

        imageUrlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:fileurl]];
        NSURLConnection *imageUrlConnection = [[NSURLConnection alloc] initWithRequest:imageUrlRequest delegate:self startImmediately:TRUE];
    } else {
        NSUInteger *count = ((NSUInteger *)[downloableImages count]);

        if (((NSUInteger *)position) < ((NSUInteger *)count - 1)) {
            position = position + 1;

            [self startDownload];
        }
    }
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"finish image...");
    NSUInteger *count = ((NSUInteger *)[downloableImages count]);

    if (((NSUInteger *)position) < ((NSUInteger *)count - 1)) {
        position = position + 1;

        [self startDownload];
    }
}

@end

For now... I only check the position of the download and current URL, Exists 27 files to download... but the download not go one by one... check this output:

Position: 0
http.....fichero00.jpg
Finish download

Position: 4
http.....fichero04.jpg
Finish download

Position: 8
http.....fichero08.jpg
Finish download

Cœur
  • 37,241
  • 25
  • 195
  • 267
jfrubiom
  • 141
  • 4
  • 11

4 Answers4

3

Create an ivar NSOperationQueue *operationQueue; in your .h file and init it in your .m file:

operationQueue = [[NSOperationQueue alloc] init];
operationQueue.maxConcurrentOperationCount = 1;

For downloading images, create a method that takes an image URL and call it for each image:

-(void)downloadImageAtURL:(NSURL *)imageURL {

    [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:imageURL] queue:operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        // Do something with your images here...
    };
}
Vinny Coyne
  • 2,365
  • 15
  • 24
  • How could I display the progress of the overall download (of all the images) using this method? – el-flor Sep 09 '15 at 10:53
2

You can try this code.. Its 100 % Working for me

You can get more reference here

-(IBAction)startdownload
{
for (int i=0; i<[downloadarray count]; i++)   //download array have url links
{ 
NSURL *URL = [NSURL URLWithString:[downloadarray objectAtIndex:i]];
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc]initWithURL:URL];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue  completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
 {
  if([data length] > 0 && [[NSString stringWithFormat:@"%@",error] isEqualToString:@"(null)"])
{
 //make your image here from data.
 UIImage *imag = [[UIImage alloc] initWithData:[NSData dataWithData:data]];
 NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,    NSUserDomainMask, YES);
 NSString *docDir = [array objectAtIndex:0];
 NSString *imgstr=[NSString stringWithFormat:@"%d",i];
 NSString *pngfilepath = [NSString stringWithFormat:@"%@sample%@.png",docDir,imgstr];
NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(imag)];
 [data1 writeToFile:pngfilepath atomically:YES];
  }
 else if ([data length] == 0 && [[NSString stringWithFormat:@"%@",error] isEqualToString:@"(null)"])
{
  NSLog(@"No Data!");
}
  else if (![[NSString stringWithFormat:@"%@",error] isEqualToString:@"(null)"]){
 NSLog(@"Error = %@", error);
 }
}];

 }

 -(IBAction)viewfile
 {
 NSMutableArray *arr=[[NSMutableArray alloc]init];

  NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,   NSUserDomainMask, YES);
 NSString *documentsDirectory = [paths objectAtIndex:0];
 NSString *pngfilepath = [NSString stringWithFormat:@"%@",documentsDirectory];
 NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:pngfilepath error:&error];
 for (int i=0; i<[filePathsArray count]; i++){
 NSString *pngfilepath = [NSString stringWithFormat:@"%@%@",documentsDirectory,  [filePathsArray objectAtIndex:i]];
 [arr addObject:[UIImage imageWithContentsOfFile:pngfilepath]];
 }
myimageview = [[UIImageView alloc] initWithImage:[arr objectAtIndex:0]]; //Here myimageview is UIImageView

 }

Hope This Helps!!!

Vishnu
  • 2,243
  • 2
  • 21
  • 44
  • Hi, I try this method... works fine to download... but I have problem when I try to update a progressView!!! "completionHandler" is really when the download are complete ?, because I have a delay when the progressView are update... – jfrubiom Feb 22 '13 at 17:29
  • @jfrubiom Can u show your completion handler part for progress view – Vishnu Feb 23 '13 at 08:46
  • Hi, I reformulate my question here http://stackoverflow.com/questions/15037791/ios-some-problems-during-download-multiple-images-and-update-uiprogressview – jfrubiom Feb 23 '13 at 13:39
1

Work around NSOperationQueue it allow you to control how much operation are run concurrently.

Create:

NSOperationQueue *queue = [NSOperationQueue new];
queue.maxConcurrentOperationCount = 1;

Then add operations :

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    ... here is you code with converting image to data and addition it to NSURLConnection
}];
[operation setCompletionBlock:^{
    ....something that you want to do, after operation completes
}];
[queue addOperation:operation];

More about NSOperation: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html#//apple_ref/occ/cl/NSOperation

Ivan Lisovyi
  • 538
  • 5
  • 13
0

Here is my new code... I have a delay when I try to update a UIProgressView

//
//  ImageDownload.m
//

#import "ImageDownload.h"

@implementation ImageDownload {
    NSMutableArray *downloableImages;
    int position;

    Sync *mySync;
}

- (void)start:(NSArray *)images sync:(Sync *)sync
{
    NSArray *imageData;
    int imageDataCount;

    mySync = sync;
    downloableImages = [[NSMutableArray alloc] init];

    for (NSArray *image in images) {
        imageData = [image valueForKey:@"image"];
        imageDataCount = [imageData count];

        if (imageDataCount > 0) {
            [downloableImages addObject:imageData];
        }
    }

    [self downloadAllFiles];
}

- (void)downloadAllFiles
{
    NSString *filename;
    NSString *fileUrl;

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *cacheDirectory = [paths objectAtIndex:0];

    position = 0;
    int count = [downloableImages count];

    NSLog(@"%@", downloableImages);
    NSLog(@"total files %d", count);

    for (NSArray *image in downloableImages) {
        filename = [image objectAtIndex:0];
        fileUrl = [image objectAtIndex:1];

        NSURL *url = [NSURL URLWithString:fileUrl];
        NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:url];

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            position++;

            float progress = (float)position / (float)count;
            //update UIProgressView
            [mySync setProgressImageDownload:progress];

            if ([data length] > 0 && [[NSString stringWithFormat:@"%@", error] isEqualToString:@"(null)"]) {
                UIImage *downloadedImage = [[UIImage alloc] initWithData:[NSData dataWithData:data]];
                NSString *imageDestinationPath = [NSString stringWithFormat:@"%@%@", cacheDirectory, filename];

                NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(downloadedImage, 100.0)];
                [imageData writeToFile:imageDestinationPath atomically:YES];
            }

            if (position == count) {
                NSLog(@"all complete...");

                [mySync downloadImagesComplete];
            }
        }];
    }
}

@end
jfrubiom
  • 141
  • 4
  • 11