0

我是 iOS 开发的新手,这是我关于 stackoverflow 的第一个问题,尽管我经常来这里。感谢提供这么好的资源!

我正在参加斯坦福 CS193P 课程,但在“作业 5 额外学分 1”方面遇到了麻烦。
我有一个显示标题、副标题和缩略图的 UITableView。我排队获取缩略图,但需要验证当缩略图图像返回时表格单元格没有被回收。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Photo";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    NSDictionary *imageDescription = [self.photoList objectAtIndex:indexPath.row];
    NSString *expectedPhotoID = [imageDescription objectForKey:FLICKR_PHOTO_ID];

    // Configure the cell...

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

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        UIImage *imageThumb = [self imageForCell:imageDescription];
        [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]]; // simulate 2 sec latency

        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *photoID = [imageDescription objectForKey:FLICKR_PHOTO_ID];
            if ([expectedPhotoID isEqualToString:photoID]) {
                cell.imageView.image = imageThumb;
            } else {
                NSLog(@"cellForRowAtIndexPath: Got image for recycled cell");
            }
        });
    });

  return cell;
}

在此代码中,photoID始终匹配expectedPhotoID. 我假设这是因为imageDescription指针在创建时用于两个队列。我试过[self.photoList objectAtIndex:indexPath.row]直接使用(代替imageDescription),但这也没有用。似乎在创建队列时也已解决。

我在这里缺少一些基本的理解,感谢您的帮助。

4

1 回答 1

1

表视图不会为所有行分配表视图单元格。相反,仅分配可见行(或更多)的单元格。如果滚动表格,一些行会消失,而其他行会出现。对于新出现的行,表格视图尝试重用不再需要的单元格。(就是dequeueReusableCellWithIdentifier:这样。)

如果您启动异步任务来检索单元格的图像,则可能会发生以下情况:

当任务完成并执行最里面的块时,单元格同时被重新用于不同的行!在这种情况下,将图像分配给单元格是没有意义的。

因此,当您拥有图像时,您必须检查单元格是否仍与之前相同。例如,您可以调用[tableView indexPathForCell:cell]并将该值与原始值进行比较indexPath。如果它们相同,则单元格仍位于同一位置,您可以分配图像。如果没有,您必须丢弃图像。

但这只是最简单的解决方案。更好的解决方案是缓存所有行的图像。

我只能推荐 WWDC 2012 Session 2011 “Building Concurrent User Interfaces on iOS”。它涵盖了这个主题。

于 2012-08-14T18:04:48.110 回答