使用reuseidentifier的UITableViewCell使用回调块提供不需要的结果

时间:2012-04-27 02:20:32

标签: objective-c uitableview objective-c-blocks reuseidentifier

当下面运行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;
}

2 个答案:

答案 0 :(得分:1)

这就是我正在做的事情。

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

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];

MessageCell是我的自定义单元格。如果您没有使用客户单元格,则可以使用Tag来检索imageView。

答案 1 :(得分:1)

我会创建一个字典来保存图像,然后尝试从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并优先处理最近请求的操作(优先处理滚动的优先级)
  • 将下载的图像保存到文件系统并先检查