Question

I have been trying to load a tableview with photos from my webserver. I am loading them asynchronously and displaying a loading spinner in the individual cells while doing so. That part works just fine, but when i then scroll and the cells get refreshed, the images disappears, but the other cell data gets loaded correctly. The funny thing is, that when i then click on the cell, the images suddenly appears! and it is also the correct images.

Anyone have an idea whats going on and possibly how to fix it?

Code below:

//
//  GalleryViewController.m
//  Photo
//
//  Created by Thomas on 5/8/14.
//  Copyright (c) 2014 Teilmann. All rights reserved.
//

#import "GalleryViewController.h"
#import "DBHandler.h"
#import "PListHandler.h"

@interface GalleryViewController ()

@end

@implementation GalleryViewController

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

@synthesize nsarray, gallery;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor colorWithRed: 0.9333 green:0.3451 blue:0.08234 alpha:1.0];

    PListHandler *userinfo = [[PListHandler alloc] initWithPlistID:@"userinfo"];
    _dbhandler = [[DBHandler alloc] init];
    NSMutableArray *test = [_dbhandler getGalleryByUserID:[userinfo getUserID]];
    gallery = [NSArray arrayWithArray:test];
    NSLog(@"test: %@", test);

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    // Return the number of rows in the section.
    return [gallery count];
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
    return @"My Gallery";
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"defaultcell" forIndexPath:indexPath];
    if(cell == nil){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"defaultcell"];
    }

    cell.imageView.image = nil;
    UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge];
    spinner.center = CGPointMake(160, 47);
    [spinner startAnimating];
    [cell.contentView addSubview:spinner];

    //hide labels until done loading
    cell.textLabel.hidden = YES;
    cell.detailTextLabel.hidden = YES;

    //download cell content async and display loading indicator in cells.
    dispatch_async(kBgQueue, ^{
        NSString *profilePicName = [NSString stringWithFormat:@"%@%@", [self.dbhandler getPicturesPath], [[gallery objectAtIndex:indexPath.row] valueForKey: @"filename"]];
        NSURL *profilepicurl = [NSURL URLWithString:profilePicName];
        NSData *imgData = [NSData dataWithContentsOfURL:profilepicurl];
        if(imgData){
            UIImage *icon = [UIImage imageWithData: imgData];
            if(icon){
                dispatch_async(dispatch_get_main_queue(), ^{
                    UITableViewCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath];
                    if(updateCell){
                        NSLog(@"hej");
                        [updateCell.imageView setImage: icon];
                        updateCell.imageView.hidden = NO;
                        NSString *subtitle = [NSString stringWithFormat:@"Comments:  %@ \nPosted:        %@", [[gallery objectAtIndex:indexPath.row] valueForKey:@"comments"], [[gallery objectAtIndex:indexPath.row] valueForKey:@"created_at"]];

                        cell.detailTextLabel.numberOfLines = 0;
                        cell.textLabel.text = [NSString stringWithFormat:@"Votes:    %@",[[gallery objectAtIndex:indexPath.row] valueForKey:@"votes"]];
                        cell.detailTextLabel.text = subtitle;

                        //Stop spinner and make labels visible
                        [spinner stopAnimating];
                        cell.textLabel.hidden = NO;
                        cell.detailTextLabel.hidden = NO;
                    }
                });
            }
        }
    });

    return cell;
}


@end
Was it helpful?

Solution

I think your problem is that you're loading the image every time the cell will be shown, remember, you're reusing cell views.

I've used https://github.com/rs/SDWebImage it has a method to cache the image and show a placeholder.

[cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

OTHER TIPS

The "cells" in your tableView are reusable. When you scroll the imageView.image is set to nil and effectively your image disappears. You have to store your images somewhere else.

Maybe in a NSDictionary that is keyed by indexPath. There you should set the image after loading it and instead of setting the image of the cell to nil, retrieve the image from the dictionary and set it on the cells imageView.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top