我在求职面试中多次提出这个问题:你有一个UITableView,用户滚动非常快。你究竟如何确保所有的细胞'从用户滚动到的任何地方都可以看到从服务器加载的图像。
我可以想到几种技巧。例如,我所做的是使用一个操作队列,加载了获取图像的请求,当用户开始滚动时,清空队列并在用户前往的任何地方填写图像请求。
另一种解决方案是用超低分辨率缩略图填充图像,例如一个4点的渐变,以便在真实图像到达之前很久就会出现一些图像,尽管图像很差。
答案 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];
}
}
这是非常基本的。显然需要更新单元格等。