iOS延迟加载表格图像

我已经使用苹果提供的示例在我的应用程序中成功实现了图片的延迟加载。 问题在于,我希望在滚动时加载图像,但只有在完成拖动后才能将图像加载到单元格中(将手指从屏幕释放,直到单元格保持空白为止)。 我修改了代码如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //NSLog(@"cell for row at indexpath, size - %f, current - %d", flowTable.contentSize.height, self.current); NSString *CellIdentifier = @"FlowCell"; MyFlowCell *cell = (MyFlowCell *)[self.flowTable dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"FlowCell" owner:nil options:nil]; // cell = [nib objectAtIndex:0]; for(id currentObject in nib) { if([currentObject isKindOfClass:[MyFlowCell class]]) { cell = (MyFlowCell *)currentObject; break; } } } ImageDetails *rowItem = [self.imageData objectAtIndex:indexPath.row]; if (!rowItem.mainImage) { // if (self.flowTable.dragging == NO && self.flowTable.decelerating == NO) // { [self startIconDownload:rowItem forIndexPath:indexPath]; //} cell.mainImage.backgroundColor = [UIColor grayColor]; } else { cell.mainImage.image = rowItem.mainImage; } } return cell; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (!decelerate) { // [self loadImagesForOnscreenRows]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { //[self loadImagesForOnscreenRows]; } 

此外,我发现在我的ImageDownloader类,NSURLConnection甚至没有收到响应,直到我释放我的手指从屏幕上。 我一直在试图找出为什么会发生这种情况,但到目前为止我还没有取得成功。 请告诉我,如果我失去了一些东西。

你可以通过以下步骤在你的tableview中实现延迟加载:

在你的Class.h中,把:

 NSMutableDictionary *Dict_name; BOOL isDragging_msg, isDecliring_msg; 

现在在Class.m文件中,把这个代码放在视图中加载:

 Dict_name = [[NSMutableDictionary alloc] init]; 

在cellForRowAtIndexPath中:

 if ([dicImages_msg valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]]) { cell.image_profile.image=[dicImages_msg valueForKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]]; } else { if (!isDragging_msg && !isDecliring_msg) { [dicImages_msg setObject:[UIImage imageNamed:@"Placeholder.png"] forKey:[[msg_array objectAtIndex:indexPath.row] valueForKey:@"image name or image link"]]; [self performSelectorInBackground:@selector(downloadImage_3:) withObject:indexPath]; } else { cell.image_profile.image=[UIImage imageNamed:@"Placeholder.png"]; } } 

对于下载图像的function是:

 -(void)downloadImage_3:(NSIndexPath *)path{ NSAutoreleasePool *pl = [[NSAutoreleasePool alloc] init]; NSString *str=[here Your image link for download]; UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:str]]]; [dicImages_msg setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:@"image name or image link same as cell for row"]]; [tableview performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO]; [pl release]; } 

最后把这些方法放在你的课堂上:

 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ isDragging_msg = FALSE; [tableview reloadData]; } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ isDecliring_msg = FALSE; [tableview reloadData]; } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ isDragging_msg = TRUE; } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView{ isDecliring_msg = TRUE; } 

更新回答:

标准的Apple LazyTableImages存在一些缺陷:

  1. 它将不会尝试检索图像,直到滚动完成。 我明白为什么他们select这样做(可能不希望检索可能会滚动的图像),但这会导致图像显得比必要的慢。

  2. 它不会将并发请求的数量限制在合理的数量。 是的, NSURLConnection会自动冻结请求,直到请求的最大数量降到一个合理的数量,但是在最坏的情况下,你实际上可以请求超时,而不是简单地排队。

  3. 一旦开始下载图像,即使该单元格随后从屏幕上滚动,也不会取消该图像。

简单的解决方法是退出IconDownloader和所有的滚动/减速逻辑,并使用SDWebImageAFNetworkingUIImageView类别。

如果你要自己解决这个问题,需要做一点工作来完成这一切。 但是这里是LazyTableImages的一个演示 ,它使用NSOperationQueue来确保我们(a)限制并发请求; 和(b)允许我们取消请求。 我承认我更喜欢上面的UIImageView类别的实现,但是我试图保留苹果的原始LazyTableImages的结构,同时弥补了我上面列举的缺陷。

假设你的UITableViewCell有一个url属性和一个图像的UIImage属性(加上队列的一个属性或静态值:

 - (void) setThumbnailUrlString:(NSString *)urlString { thumbnailUrlString = urlString; NSURL *url = [NSURL URLWithString:urlString]; NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url]; if ( queue == nil ) { queue = [[NSOperationQueue alloc] init]; } [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse * resp, NSData *data, NSError *error) { dispatch_async(dispatch_get_main_queue(),^ { if ( error == nil && data ) { UIImage *urlImage = [[UIImage alloc] initWithData:data]; thumbnail.image = urlImage; } }); }]; } 

你的实现的问题是你的图像加载方法可能发生在主线程中。 您需要asynchronous加载图像,然后在主线程中更新图像。

为了正确,块应检查响应的url是否匹配请求的url,如果单元格的图像加载太迟之前,单元格被重新用于不同的图像。

我已经做了这个框架,其中包含懒惰的负载控制器。 它很容易使用和开箱即用。 https://github.com/cloverstudio/CSUtils教程可以在这里find: http : //www.clover-studio.com/blog/using-csutils-ios-framework-for-lazy-loading-images/

这是相当晚的答案,但随着iOS版本的变化,方法不断变化。

为了延迟加载图像,这里是推荐的方法:

  1. 下载所有图像的URL并将其存储到您的容器(数组/对象等)
  2. 触发在后台队列上运行asynchronous的NSURLSessionTask (仅适用于iOS 7)。 如果您的iOS 7以下,您可以使用NSURLConnection SendAsynchronousRequest API – 它已被弃用在iOS 9,所以你最好摆脱这一点。
  3. 在后台队列上创build图片
  4. 回到主队列,确保你有正确的UITableViewCell,然后更新图像

这里 – 整个方法在我的教程中描述 。