从 Document 目录加载多个图像时 UICollectionView 卡住
Posted
技术标签:
【中文标题】从 Document 目录加载多个图像时 UICollectionView 卡住【英文标题】:UICollectionView Stuck when loading multiple images from Document directory 【发布时间】: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]]]];
这个我试过了,但是不行
【参考方案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 您能否在清除所有图像的缓存后尝试一下,请查看此答案以获取更多详细信息***.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;
,以上是关于从 Document 目录加载多个图像时 UICollectionView 卡住的主要内容,如果未能解决你的问题,请参考以下文章
从/在一个目录中加载/保存多个图像 - opencv c++