UITableViewCell使用重用标识符给出不需要的结果和回调块



当下面运行 loadImage 的回调块时,表单元格可能已被重用。因此,应用于"imageView"的图像与这个重用的单元格无关,它是旧单元格的图像。

如果我使每个具有图像的单元格的标识符是唯一的,则问题就会消失。 但这会产生许多结果的不良性能。

我可以以某种方式将相同的重用标识符与回调块一起使用并让图像出现在正确的单元格中吗?

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSDictionary *place;
    PlaceTableViewCell *cell; // UITableViewCell subclass
    NSString *identifier = @"PlaceTableViewCell";
    if (cell == nil) {
        NSArray *objects;
        objects = [[NSBundle mainBundle] loadNibNamed:@"PlaceTableViewCell" owner:self options:nil];
        for(id object in objects) {
            if([object isKindOfClass:[PlaceTableViewCell class]]) {                
                cell = (PlaceTableViewCell *)object;                
                break;
            }
        }
    }
    UIImageView *imageView;
    if((imageView = (UIImageView*)[cell viewWithTag:1])) {
        NSString *filename;
        int placeImageId = 0;
        place = [places objectAtIndex:indexPath.row];
        if(place) {
            placeImageId = [[d objectForKey:@"placeImageId"] intValue];
            if(placeImageId) {
                [[RestAPIConnector sharedInstance] loadImage :placeImageId :@"thumb" :^(NSString *response){
                    NSDictionary *image = [response JSONValue];
                    if ([image objectForKey:@"img"]) {
                        NSString *b64Img = [image objectForKey:@"img"];
                        UIImage *ui = [UIImage imageWithData:[Base64 decode:b64Img]];
                        imageView.image = ui;
                    }
                }];            
            }
        }
    }
    return cell;
}

这就是我正在做的事情。

而不是直接使用单元格,我传递索引路径

if(user.profileImage == nil)
{
    if (self.tableView.dragging == NO && self.tableView.decelerating == NO) {
        NSLog(@"file for user %d doesn't exist", [user.userId intValue]);
        [self startUserProfileImageDownload:user forIndexPath:indexPath];
    }
}
else
{
    cell.profileImageView.image = user.profileImage;
}

下载完成后,使用索引路径检索单元格并更新映像

MessageCell *cell = (MessageCell *)[self.tableView cellForRowAtIndexPath:path];
// Display the newly loaded image
cell.profileImageView.image = user.profileImage;
CALayer *roundedLayer = [cell.profileImageView layer];

消息单元格是我的自定义单元格。如果没有"使用客户单元格",则可以使用 Tag 检索图像视图。

我会创建一个字典来保存图像,然后尝试从字典中读取cellForRowAtIndexPath:

@property(retain)NSMutableDictionary *imageData;
//...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //...
    UIImageView *imageView;
    if((imageView = (UIImageView*)[cell viewWithTag:1])) {
        int placeImageId = 0;
        place = [places objectAtIndex:indexPath.row];
        if(place) {
            placeImageId = [[d objectForKey:@"placeImageId"] intValue];
            if(placeImageId) {
                NSObject *image = [imageData objectForKey:[NSNumber numberWithInt:placeImageId]];
                if ([image isKindOfClass:[UIImage class]) {
                    imageView.image = (UIImage *)image;
                } else if (![image isEqual:@"downloading"]) {
                    [imageData addObject:@"downloading" forKey:[NSNumber numberWithInt:placeImageId]];
                    [[RestAPIConnector sharedInstance] loadImage:placeImageId onSuccess:^(NSString *response){
                        NSDictionary *image = [response JSONValue];
                        if ([image objectForKey:@"img"]) {
                            NSString *b64Img = [image objectForKey:@"img"];
                            [imageData addObject:[UIImage imageWithData:[Base64 decode:b64Img]] forKey:[NSNumber numberWithInt:placeImageId]];
                        }
                    }];            
                }
            }
        }
    }
    return cell;
}

一些潜在的优化:

  • 与@Jun1st的示例一样,滚动时不要加载单元格的图像
  • 将下载操作添加到NSOperationQueue并首先确定最近请求的操作的优先级(取消滚动操作的优先级)
  • 将下载的图像保存到文件系统并首先检查

最新更新