UITableview dequeueReusableCellWithIdentifier和UIImageView问题?

时间:2012-05-10 11:55:35

标签: iphone cocoa-touch ipad uitableview

我正在将异步图像加载到UITableView中,每行都有不同的图像。问题是当我滚动UITableView时,先前的图像再次加载到新行中,一段时间后这些图像被更改为正确的(当我删除 dequeueReusableCellWithIdentifier 时,这个问题就消失了但是它减少了性能)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
     static NSString *cellIdentifier = @"Cell"; 
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

     if(cell == nil) {
        NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomCellFriends" owner:self options:nil];
        cell = [nibObjects objectAtIndex:0];  
        nibObjects = nil;
     } 

     UIImageView *avatar = (UIImageView *)[cell viewWithTag:100];
     UILabel *name = (UILabel *)[cell viewWithTag:2];
     UILabel *city = (UILabel *)[cell viewWithTag:3];

     EntryProfile *entryForRow = [entriesProfileArray objectAtIndex:indexPath.row];


    avatar.image = nil;

     NSString *strLinkImage = [entryForRow.apiAvatarPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
     NSArray *args = [NSArray arrayWithObjects:avatar,strLinkImage,[NSString stringWithFormat:@"%d",indexPath.row], nil];
     NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(addPhotoWithImageView:) object:args];
     [operationQueue addOperation:operation];
     [operation release];

     // Set the name of the user
     name.text = entryForRow.name;

     return cell;
}

// Method 
- (void)addPhotoWithImageView:(NSArray *)args
{
    UIImageView *imageView = (UIImageView *)[args objectAtIndex:0];
    NSString *strLinkImage = (NSString *)[args objectAtIndex:1];
    NSString *index = (NSString *)[args objectAtIndex:2];

    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.example.com%@",strLinkImage]]];
    UIImage *imageField = [[UIImage alloc] initWithData:imageData];

    if (imageData) {
        [imageView performSelectorOnMainThread:@selector(setImage:) withObject:imageField waitUntilDone:NO];
    }
    [imageField release];
 }

5 个答案:

答案 0 :(得分:3)

如果有人仍然面临这个问题,我看到上面的答案并没有真正帮助。

采取以下两个步骤:

  • 您需要“取消”正在进行的图像视图的异步请求,然后使用占位符图像异步设置新图像,直到异步请求通过
  • 理想情况下,在用户滚动浏览时不要发送异步请求 (tableview / scrollview正在减速) - 尽量避免发出新请求,只是在这种情况下设置占位符(除非你有办法自信地知道请求是在之前完成的,因此可能是在本地找到了图像图像URL的磁盘缓存)

以上两个步骤将使您的功能保持正常,并为您提供良好的性能。

答案 1 :(得分:0)

在cellForRowAtIndexPath中

, 在你打电话之前:

 NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(addPhotoWithImageView:) object:args];

强制yourCell imageView.image为nil

imageView.image = nil;

这样你就可以清理旧单元格的内容图像,然后在加载时用正确的图像重绘...

修改

也许零不起作用......

尝试一个placeHolder图像,一个真正的png文件(带有颜色,用于测试,然后它可能是一个透明文件......)

答案 2 :(得分:0)

尝试实现自己的UItableViewCell,并在PrepareForReuse方法中将所有单元格属性设置为nil。

我还建议你看看这个项目,以便加载异步远程图像: https://github.com/nicklockwood/AsyncImageView

我在不同的项目中取得了巨大的成功。

答案 3 :(得分:0)

前几天有一个类似的问题和我解决它的方式是以下(我没有注意到任何性能下降)。

UITableViewCell *cell;

if (cell == nil) {
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

// rest of the code

}

所以基本上调用if。

中的dequeue

答案 4 :(得分:0)

这是一个经典问题,很容易解决。

cellForRowAtIndexPath:实施中,您可以包含以下代码:

if (!tableView.decellerating) {
    // set avatar.image to its correct UIImage value how ever you like, 
    // in the background if necessary
} else {
    // table is scrolling...
    avatar.image = nil;
}

然后在视图控制器中实现此方法:

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSArray *visibleCells = [self.tableView visibleCells];
    [visibleCells enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        UITableViewCell *cell = (UITableViewCell *)obj;
        UIImageView *avatar = (UIImageView *)[cell viewWithTag:100];
        avatar.image = ...; // Do what you need to do to set the image in the cell
    }];
}

您还需要将UIScrollViewDelegate添加到视图控制器采用的协议列表中。

这里的想法是,只要表视图移动,就不要费心加载图像。你的表现会飙升。