简体   繁体   中英

Asynchronously load image in uitableviewcell

I am trying to asynchronously load an image in a UITableVIew .

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

UITableViewCell *cell = nil;
NSString *cellIndetify = [NSString stringWithFormat:@"cell%d",tableView.tag -TABLEVIEWTAG];

cell = [tableView dequeueReusableCellWithIdentifier:cellIndetify];
IndexPath *_indextPath = [IndexPath initWithRow:indexPath.row  withColumn:tableView.tag - TABLEVIEWTAG];
if (cell == nil) {

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIndetify];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    cell.contentView.backgroundColor = [UIColor blackColor];
// here I init cell image view
        UIView *cellSub =  [self.waterFlowViewDatasource waterFlowView:self cellForRowAtIndexPath:_indextPath];

    cellSub.backgroundColor = [UIColor blackColor];
    [cell.contentView addSubview:cellSub];
    cellSub.tag = CELLSUBVIEWTAG;

}
// fill image info 
    [self.waterFlowViewDatasource waterFlowView:self fillDataIntoCellSubview:[cell viewWithTag:CELLSUBVIEWTAG] withIndexPath:_indextPath];


CGFloat cellHeight = [self.waterFlowViewDelegate waterFlowView:self heightForRowAtIndexPath:_indextPath];

CGRect cellRect = CGRectMake(0, 0, _cellWidth, cellHeight);
[[cell viewWithTag:CELLSUBVIEWTAG] setFrame:cellRect];


[self.waterFlowViewDatasource waterFlowView:self relayoutCellSubview:[cell viewWithTag:CELLSUBVIEWTAG] withIndexPath:_indextPath];

return cell;
}

in that ImageView class I init:

(id)initWithIdentifier:(NSString *)indentifier
{
    if(self = [super initWithIdentifier:indentifier])
    {
        self.backgroundColor = [UIColor blackColor];

        if (!self.imageView) {
            _imageView = [[UIImageView alloc] init];
            self.imageView.backgroundColor = IMAGEVIEWBG;
            [self addSubview:self.imageView];

            self.imageView.layer.borderWidth = 1;
            self.imageView.layer.borderColor = [[UIColor colorWithRed:0.85 green:0.85 blue:0.85 alpha:1.0] CGColor];
        }
        ......some others controllers
}

-(void)setImageWithURL:(NSURL *)imageUrl{


    UIImage *cachedImage = [[SDImageCache sharedImageCache] imageFromKey:[imageUrl absoluteString]];
    if (cachedImage) {
        self.imageView.image = cachedImage;
    }else{
        SDWebImageManager *manager = [SDWebImageManager sharedManager];
            [manager downloadWithURL:imageUrl delegate:self options:SDWebImageCacheMemoryOnly userInfo:[[NSDictionary alloc] initWithObjectsAndKeys:[imageUrl absoluteString], @"image_url", [NSValue valueWithBytes:&imageSize objCType:@encode(CGSize)], @"image_size", [NSNumber numberWithInt:arrIndex], @"imageview_index", nil]];
            _imageView.image = [UIImage imageNamed:@"album_detail_placeholder.png"];
}
.....
.....

- (void)imageDecoder:(SDWebImageDecoder *)decoder didFinishDecodingImage:(UIImage *)image userInfo:(NSDictionary *)userInfo {

       imageView.image = image
}

As you see here I used SDWebImageManager, but that doesn't seem to be the problem.

When pull up to next page, before the next page's images have loaded, if I scroll back to previous page's loaded image, the image will be covered by another image (which is should display in the newest page, not current page...) (for example, in the first page, I have a image and there is cat in this image, and then I scroll down till pull up to request next page, and after get all next page image's url, start asynchronous thread download images, before the newest images downloaded, scroll back to top, maybe first page. After awhile, some images downloaded, they should display in there cell, but now the images will cover the current page images, maybe the cat image now have a dog image on it) what shall I do?

When a row is scrolled off-screen, the table view reuses that row's cell for another row that has scrolled on-screen.

The problem is that you are using the ImageView as the delegate of the background loader, and the ImageView is associated with a cell, not a row. By the time the background loader finishes loading the image, the cell may have been reused for another row.

You need to make the table view's data source be the delegate for the background image loader. It should put the index path of the row into the userInfo dictionary when it calls downloadWithURL:delegate:options:userInfo: . When the downloader sends imageDecoder:didFinishDecodingImage:userInfo: to the data source, the data source should get the index path out of the userInfo and use it to ask the table view for the cell currently displaying that row (by sending cellForRowAtIndexPath: to the table view).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM