【问题标题】:UICollectionView Stuck when loading multiple images from Document directory从 Document 目录加载多个图像时 UICollectionView 卡住
【发布时间】:2018-08-07 10:21:58
【问题描述】:

我正在加载超过 30-50 张图像,这些图像存储在文档目录中。他们所有的图像都立即加载到collectionView,但是当滚动collectionView时它会卡住。

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"ImageCell";
    ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

    //Load image from document  directory
    NSString *imageName = [arrCollection objectAtIndex:indexPath.row];
    NSString *imagePath = [NSString stringWithFormat:@"%@/%@",(AppObj).imagefolderPath, imageName];
    UIImage *localImg = [[UIImage alloc]initWithContentsOfFile:imagePath];

    cell.imgSketch.image = localImg;

    cell.txtName.text = [NSString stringWithFormat:@"%@",[imageName stringByReplacingOccurrencesOfString:@".png" withString:@""]];

    cell.layer.masksToBounds = YES;
    return cell;
}

我也尝试了以下调度块

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
                UIImage *localImg = [[UIImage alloc]initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",(AppObj).imagefolderPath,[arrCollection objectAtIndex:indexPath.row]]];
                dispatch_async(dispatch_get_main_queue(), ^{
                    cell.imgSketch.image = localImg;
                });
            });

请建议我解决此问题的任何解决方案。

提前致谢

【问题讨论】:

  • 可能是预取也可以帮助您解决以下问题
  • 最好的解决方案是使用一些图像缓存库,如 SDWebImage,它非常易于使用,并且以异步方式加载和缓存图像。 github.com/rs/SDWebImage
  • @vivekDas 我认为当我们想从 Web URL 加载图像时使用 SDWebImage
  • 您可以尝试使用 imagePath 而不是 web url 来检查它是否有效。
  • @vivekDas [cell.imgSketch sd_setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/%@",(AppObj).imagefolderPath,[arrCollection objectAtIndex:indexPath.row]]]];这个我试过了,但是不行

标签: ios objective-c asynchronous uicollectionview


【解决方案1】:

您可以使用SDWebImage 也可以显示文档目录中的图像。

[cell.imgSketch sd_setImageWithURL:[NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@",(AppObj).imagefolderPath,[arrCollection objectAtIndex:indexPath.row]]]];

注意:在创建NSURL 的对象时使用fileURLWithPath,因为它是文件的路径。

【讨论】:

  • 如何删除缓存中的图片?我试过这个,但它不起作用[[SDImageCache sharedImageCache] removeImageForKey:[NSString stringWithFormat:@"%@/%@",(AppObj).imagefolderPath,[arrCollection objectAtIndex:sender.tag]] fromDisk:YES withCompletion:nil];
  • @MonikaPatel 实际上这应该可以工作,代码看起来正确,你怎么知道图像没有从缓存中删除?
  • 实际上我的应用程序只能在本地工作,现在用户可以将多个图像从图库导入到我的应用程序。所有图像名称都按此顺序 img1,img2,im3....n。现在的重点是,如果用户选择 3 张图片并在我的应用程序中导入所有 3 张图片。所以现在图像名称是分配 img1,img2,im3。现在用户删除这 3 个图像并导入新的 3 个图像。同样,图像名称将为 img1、img2、img3。所以这些 img1,img2,img3 图像从缓存中获取旧图像。它将显示已删除的旧图像,其中包含新的 3 张选定图像。
  • @MonikaPatel 您能否在清除所有图像的缓存后尝试一下,请查看此答案以获取更多详细信息stackoverflow.com/a/39881690/6433023
【解决方案2】:

我的建议是将您的图像加载操作移至后台线程。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
   UIImage* localImage = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",(AppObj).imagefolderPath,[arrCollection objectAtIndex:indexPath.row]]];    
   dispatch_async(dispatch_get_main_queue(), ^{
      cell.imgSketch.image = localImage;
   });
});

【讨论】:

  • 对不起,这个解决方案我已经试过了,但是不行。
【解决方案3】:

我建议在cellForRowAt 中只加载一次所有图像

NSMutableArray*images; // every instance is of type UIImage not imageName

而不是这个

UIImage *localImg = [[UIImage alloc]initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@",(AppObj).imagefolderPath,[arrCollection objectAtIndex:indexPath.row]]];

注意:这个方法initWithContentsOfFile在mainQueue中运行所以是卡住的主要原因

【讨论】:

    【解决方案4】:

    如果我们使用大图像,collectionview/tableview 单元格会闪烁。尝试使用小尺寸图片或在后台队列中的cellForItemAtIndexPath 创建一张。

    您可以通过在数组中缓存图像来提高性能。 注意:如果容量增加限制,请尝试清理它。

    cell.imgSketch.image = nil;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    
         UIImage *localImg = [[UIImage alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", (AppObj).imagefolderPath, [arrCollection objectAtIndex:indexPath.row]]];
    
         NSData *imgData = UIImageJPEGRepresentation(localImg, 0.5);
         localImg = [UIImage imageWithData:imgData];
    
         dispatch_async(dispatch_get_main_queue(), ^{
             ImageCell *imageCell = [collectionView cellForItemAtIndexPath:indexPath];
             if (imageCell) {
                 cell.imgSketch.image = localImg;
             }
        });
    });
    

    【讨论】:

    • 您的代码很有帮助,但是当我滚动 collectionView 时,imageview 中的随机图像绑定和图像会在滚动过程中发生变化。
    • 在从文件管理器加载之前设置cell.imgSketch.image = nil;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 2019-01-03
    相关资源
    最近更新 更多