user1163463
user1163463

Reputation:

Table view mixes up images

I use SDWebImage to load and display async images in TableView. But sometimes when I scroll up and down fast, it mixes up all images and display it in other rows. This is my cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {

        cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

    } 

// Configure the cell.

MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];

if (item) {


        // Parse out Image URL for cell

        if (cell.imageView.image == nil) {

        NSError *error = NULL;

        NSRegularExpression *regexImage = [NSRegularExpression regularExpressionWithPattern:@"(<img\\s[\\s\\S]*?src\\s*?=\\s*?['\"](.*?)['\"][\\s\\S]*?>)+?"

                                                                               options:NSRegularExpressionCaseInsensitive

                                                                                error:&error];
        [regexImage enumerateMatchesInString:item.content

                                options:0

                                  range:NSMakeRange(0, [item.content length])

                             usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {



                                 NSString *src = [item.content substringWithRange:[result rangeAtIndex:2]];

                                 NSLog(@"img src: %@", src);

                                 [cell.imageView setImageWithURL:[NSURL URLWithString:src]];

                             }];}



        if (cell.imageView.image  == nil) {

            cell.imageView.image = [UIImage imageNamed:@"video.png"];

}

    return cell;

}

I don't know what is wrong, but I think its because I parse the image in the cell and it is not fast enough so it starts again and again. Can you please show me how to fix that

Upvotes: 1

Views: 209

Answers (2)

B.S.
B.S.

Reputation: 21726

Change cell identifier from

static NSString *CellIdentifier = @"Cell"; 

to

NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%i",indexPath.row];

Upvotes: 0

Charlie Price
Charlie Price

Reputation: 1376

The high-level answer is, I believe, that when you scroll you are reusing the cells before you complete putting an image into them. That's what it means when I see this in my code, anyway.

I don't use SDWebImage and I don't know exactly what setImageWithURL variants are, but the github webpage has a how-to-use that says you can give it a completion block to execute when the image fetch is done (succeeds or fails). So you need to check, when you finally have the image but before you put it in the UITableViewCell, that the cell is still assigned to the same indexPath as when you started to get the image. Since setImageWithURL seems to set the image always, you will have to put have a temporary UIImageView rather than directly in the cell. The docs I looked at had a method call with both placeHolderImage: and completed: Using that you'd do something like (code not compiler checked):

// before you go off to get the image, save the indexPath of the cell
NSIndexPath *originalIndexPath = indexPath;
UIImageView *tempImageView;
[tempImageView setImageWithURL:[NSURL URLWithString : [NSURL URLWithString:src]]
           placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                  completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
    // completion block
    // You probably want to check that it really succeeded, but if it did
    // Now you have an image in the image parameter and probably in tempImageView.
    // Check to see if the cell is still at the original indexPath
    // If so, put the image in.
    // If not, the row was scrolled out of sight and the cell has been reused
    // so just drop the image on the floor -- it is no longer useful
    NSIndexPath *currentIndexPath = [self.tableview indexPathForCell:cell]
    if ([currentIndexPath isEqual originalIndexPath]) {
        cell.imageView.image = image;
        // or perhaps: cell.imageView.image = tempImageView.image;
    }
}];

Upvotes: 4

Related Questions