1

I have a TableView with customCells, when user press Start button on some cell the loading starts. There are many such cells, so I need to implement this downloading in parallel (asynchronously). For image downloading and updating the cell in Table view I use next code:

#define myAsyncQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

I include this method into the async queue, that I supposed should enable parallel downloading of images. - (void)didClickStartAtIndex:(NSInteger)cellIndex withData:

    (CustomTableViewCell*)data
    {
 dispatch_async(myAsyncQueue, ^{        
self.customCell = data;
        self.selectedCell = cellIndex;
        ObjectForTableCell* tmp =[self.dataDictionary objectForKey:self.names[cellIndex]];

        NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:tmp.imeageURL]
                                                    cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                timeoutInterval:60.0];
        self.connectionManager = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
       }); 
    }
    -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
          self.urlResponse = response;

        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
        NSDictionary *dict = httpResponse.allHeaderFields;
        NSString *lengthString = [dict valueForKey:@"Content-Length"];
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        NSNumber *length = [formatter numberFromString:lengthString];
        self.totalBytes = length.unsignedIntegerValue;

        self.imageData = [[NSMutableData alloc] initWithCapacity:self.totalBytes];
    }

    -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
           [self.imageData appendData:data];
        self.customCell.progressView.progress = ((100.0/self.urlResponse.expectedContentLength)*self.imageData.length)/100;
          float per = ((100.0/self.urlResponse.expectedContentLength)*self.imageData.length);
        self.customCell.realProgressStatus.text = [NSString stringWithFormat:@"%0.f%%", per];

    }

   I tried to set this block to queue - main queue - cause its the place where image is already downloaded,

        -(void)connectionDidFinishLoading:(NSURLConnection *)connection
        {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.customCell.realProgressStatus.text = @"Downloaded";

            UIImage *img = [UIImage imageWithData:self.imageData];
            self.customCell.image.image = img;
            self.customCell.tag = self.selectedCell;
    });
            [self.savedImages setObject:img forKey:self.customCell.nameOfImage.text];
            NSNumber *myNum = [NSNumber numberWithInteger:self.selectedCell];
            [self.tagsOfCells addObject:myNum];
       }

Without all queues(when I comment it)all works properly - but just 1 downloading at a ones. But when I tried to implement code with queues as a result it doesn't download anything. I understand that I did smh wrong but I can't define it.

Thanks a lot for any help in advance.

Melany
  • 466
  • 7
  • 20
  • 2
    [just try this lib](https://github.com/rs/SDWebImage) – Fahim Parkar Mar 28 '16 at 09:48
  • @Fahim, thank you for an advice , I am learning, and wanted to implement it by myself, without any third party library, well at least try to do it by myself – Melany Mar 28 '16 at 10:02

2 Answers2

2

Use this sample code from Apple to solve your problem of lazy loading.

Waris Shams
  • 1,606
  • 1
  • 15
  • 27
2

If your looking out for starting it form basics I guess you should start with NSURLSession as NSURLConnection most of implementation had been deprecated and won't be available after iOS 9. For complete reference URL Session Programming Guide and tutorial

Coming back to your question you should do something similar to this took it from tutorial

// 1
NSURLSessionDownloadTask *getImageTask =
[session downloadTaskWithURL:[NSURL URLWithString:imageUrl]

    completionHandler:^(NSURL *location,
                        NSURLResponse *response,
                        NSError *error) {
        // 2
        UIImage *downloadedImage =
          [UIImage imageWithData:
              [NSData dataWithContentsOfURL:location]];
      //3
      dispatch_async(dispatch_get_main_queue(), ^{
        // do stuff with image
        _imageWithBlock.image = downloadedImage;
      });
}];

// 4
[getImageTask resume];

But my personal recommendation is go for AFNetworking which is best for iOS networking and widely used/tested in iOS app world.

For image download using AFNetworking

[_imageView setImageWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://i.imgur.com/fVhhR.png"]]
                      placeholderImage:nil
                               success:^(NSURLRequest *request , NSHTTPURLResponse *response , UIImage *image ){
                                   NSLog(@"Loaded successfully: %d", [response statusCode]);
                               }
                               failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
                                   NSLog(@"failed loading: %@", error);
                               }
    ];

EDIT : Async downloading using concurrency

// get main dispact queue
dispatch_queue_t queue = dispatch_get_main_queue();
// adding downloading task in queue using block
dispatch_async(queue, ^{
  NSData* imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]];
  UIImage* image = [[UIImage alloc] initWithData:imageData];
  // after download compeletes geting main queue again as there can a possible crash if we assign directly
  dispatch_async(dispatch_get_main_queue(), ^{
    _imageWithBlock.image = image;
  });
});
aman.sood
  • 872
  • 7
  • 19
  • thank you vey much, yes I know that NSURLConnection is deprecated , I will move to NSURLSession, but currently I need to solve this issue in current project – Melany Mar 28 '16 at 11:52
  • 2
    then this must be helpful http://stackoverflow.com/questions/12655360/images-downloaded-asynchronously-only-appear-in-uitableview-after-tap-or-scroll – aman.sood Mar 28 '16 at 12:03
  • Thank you very much for help)). – Melany Mar 28 '16 at 12:57