Carga de imagen UITableViewCell desde url

I have a problem with loading an image from an url to display in a table. I currently have the following code to handle the image loading in a class that extends UITableViewCell:

- (void) initWithData:(NSDictionary *) data{

     NSDictionary *images = [data objectForKey:@"images"];
    __block NSString *poster = [images objectForKey:@"poster"];

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{

            NSURL *posterURL = [[NSURL alloc] initWithString:poster];
            NSData *imageData = [NSData dataWithContentsOfURL:posterURL];

            if (imageData != nil) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    // 4. Set image in cell
                    self.backgroundImage.image = [UIImage imageWithData:imageData];
                    [self setNeedsLayout];

    self.backgroundImage.image = [UIImage imageNamed:@"static"];

The initWithData method is called from the ViewController in the tableView:cellForRowAtIndexPath: delegate. Everything works as expected until i scroll. From what i read, the TableView cells are recycled and because the images are being loaded async, i get rows with wrong images. También el images are not cached and are loaded again whenever the cell is displayed.

Eg: Scroll to the middle and immediately scroll back up. The first cell will have the image that's corresponding to the middle cell that didn't get to finish loading.

Any help or suggestions? Thank you very much :)

preguntado el 27 de noviembre de 13 a las 18:11

You can use SDWebImage -

Thanks i'll try using SDWebImage. But this might not be the real problem... -

If you want caching of image then best to go with SDWebImageView. Yes this is not the problem. If you don't want to use it, then first check whether Image is downloaded or not, then only allow download request. You current implementation is not doing that. -

1 Respuestas

First of all as the comment mentioned, I would definitely recommend using an existing framework/component to do this job.

The best candidates are probably:

OR if you also want a general networking library

That said, if you still want to try it on your own, you would probably want to implement caching with an NSMutableDictionary using the indexPath as the key, and the image as the value.

Assuming you have an initialized instance variable NSMutableDictionary *imageCache

En su cellForRowAtIndexPath method, before attempting to do any image loading, you would check to see if your cache already has an image for this index by doing something like this

if(! imageCache[indexPath])
  // do your web loading here, then once complete you do
  imageCache[indexPath] = // the new loaded image
  self.backgroundImage.image = imageCache[indexPath];

respondido 27 nov., 13:18

No, it should be an instance variable declared in the containing class and initialized before the table begins loading (so in init or viewDidLoad o algo así). - Dima

Puede modificar su initWithData method to also pass in the indexPath y el imageCache and then this will still work as it should. So the method declaration would be initWithData:indexPath:imageCache: - Dima

just pass in the pointer as you normally would. it is mutable and can be modified by whatever you're passing it to. So initWithData:(NSDictionary *)data indexPath:(NSIndexPath *)indexPath imageCache:(NSMutableDictionary *)imageCache - Dima

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.