如何确保UITableView单元格中的远程获取图像始终填充?

时间:2015-04-29 14:21:18

标签: ios objective-c uitableview uiimage remote-server

我在求职面试中多次提出这个问题:你有一个UITableView,用户滚动非常快。你究竟如何确保所有的细胞'从用户滚动到的任何地方都可以看到从服务器加载的图像。

我可以想到几种技巧。例如,我所做的是使用一个操作队列,加载了获取图像的请求,当用户开始滚动时,清空队列并在用户前往的任何地方填写图像请求。

另一种解决方案是用超低分辨率缩略图填充图像,例如一个4点的渐变,以便在真实图像到达之前很久就会出现一些图像,尽管图像很差。

2 个答案:

答案 0 :(得分:0)

我会说"清空队列并在用户前往的任何地方填写图像请求"使用indexPathsForVisibleRows是正确的。但是图像永远不会立即出现,除非它们非常小。

我认为他们的意思是在从后台线程下载后立即显示下载的图像,即:dispatch_get_main_queue()

在.h文件中:

@interface ViewController : UIViewController <UIScrollViewDelegate>

在.m文件中:

- (void)downloadVisibleRowImages
{
    NSArray *visibleRows = [self.tableView indexPathsForVisibleRows];

    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
        for (NSIndexPath *visibleRow in visibleRows) {
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath: visibleRow];
            NSString *imageUrl = [_responseImages objectAtIndex:visibleRow.row];
            UIImage *image = nil; // Download image here
            dispatch_async(dispatch_get_main_queue(), ^{ // use main thread to display image immediately after download
                if (image) [cell.imageView setImage:image];
            });
        }
    });
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate) {
        [self downloadVisibleRowImages];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self downloadVisibleRowImages];
}

答案 1 :(得分:0)

我想说这里的关键是“用户滚动到哪里”。因此,在知道哪些单元格可见之前,不应该开始下载图像。

所以我要做的是观察UIScrollViewDelegate调用:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

此时,使用以下方法显示单元格:

- (NSArray *)indexPathsForVisibleRows

然后关闭我的图片下载。把它们放在一起:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSArray *theIndexPaths = [self.tableView indexPathsForVisibleRows];
    for (NSIndexPath *theIndexPath in theIndexPaths) {
        SomeObject *myObject = self.listOfMyObjects[theIndexPath.row];
        [myObject downloadImage];
    }
}

这是非常基本的。显然需要更新单元格等。