3

I've been researching and haven't found any answer to this question - sendAsynchronousRequest vs. dataWithContentsOfURL.

Which is more efficient? more elegant? safer? etc.

- (void)loadImageForURLString:(NSString *)imageUrl
{
    self.image = nil;

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse * response, NSData * data, NSError * connectionError)
     {
         [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
         if (data) {
             self.image = [UIImage imageWithData:data];
         }
     }];
}

OR

- (void)loadRemoteImage
{
    self.image = nil;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        NSData * imageData = [NSData dataWithContentsOfURL:self.URL];
        if (imageData)
            self.image = [UIImage imageWithData:imageData];

        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.image) {
                [self setupImageView];
            }
        });
    });
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
Yariv Nissim
  • 13,273
  • 1
  • 38
  • 44

2 Answers2

1

So I've come up with an answer for my own question:
Currently there are 3 main ways to load images async.

  1. NSURLConnection
  2. GCD
  3. NSOperationQueue

Choosing the best way is different for every problem.
For example, in a UITableViewController, I would use the 3rd option (NSOperationQueue) to load an image for every cell and make sure the cell is still visible before assigning the picture. If the cell is not visible anymore that operation should be cancelled, if the VC is popped out of stack then the whole queue should be cancelled.

When using NSURLConnection + GCD we have no option to cancel, therefore this should be used when there is no need for that (for example, loading a constant background image).

Another good advice is to store that image in a cache, even it's no longer displayed, and look it up in cache before launching another loading process.

Yariv Nissim
  • 13,273
  • 1
  • 38
  • 44
0

sendAsynchronousRequest is better, elegant and whatever you call it. But, personally, I prefer creating separate NSURLConnection and listen to its delegate and dataDelegate methods. This way, I can: 1. Set my request timeout. 2. Set image to be cached using NSURLRequest's cache mechanism (it's not reliable, though). 2. Watch download progress. 3. Receive NSURLResponse before actual download begins (for http codes > 400). etc... And, also, it depends on cases like, image size, and some other requirements of your app. Good luck!

Fahri Azimov
  • 11,470
  • 2
  • 21
  • 29
  • Download progress is the biggest advantage for me to use delegates - however it seems that the response always shows 0 on the estimated size for the image. Is a problem on the server side? Other than that, I think the delegate is the messiest method. – Yariv Nissim Oct 29 '12 at 22:00