我正在使用以下代码从PHAsset获取图像和AVAsset。这是代码中的两个数组:
galleryArr
:存储图像以供收藏夹视图。
mutableDataArr
:存储要存储在服务器上的图像(用于图像资产)和视频(用于AVAset)
从PHAssets数组中获取所有图像非常慢。 我用谷歌搜索,大多数人说删除此行[options setSynchronous:YES];但是,如果我删除此行,则完成被调用两次,并且数组复制对象(因为对象在完成时被追加到数组中)。
for (int i = 0; i < assets.count; i++) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic;
options.resizeMode = PHImageRequestOptionsResizeModeExact;
[options setNetworkAccessAllowed:YES];
[options setSynchronous:YES];
PHImageManager *manager = PHImageManager.defaultManager;
PHVideoRequestOptions *videoOptions = [[PHVideoRequestOptions alloc] init];
videoOptions.networkAccessAllowed = YES;
__weak typeof(self) weakSelf = self;
if (assets[i].mediaType == PHAssetMediaTypeVideo) {
[manager requestAVAssetForVideo:[assets objectAtIndex:i] options:videoOptions resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
if ([asset isKindOfClass:[AVURLAsset class]])
{
[weakSelf.mutableDataArr addObject:asset];
}
}];
}
[manager requestImageForAsset:[assets objectAtIndex:i]
targetSize: CGSizeMake(1024, 1024) //PHImageManagerMaximumSize
contentMode:PHImageContentModeAspectFit
options:options
resultHandler:^(UIImage *image, NSDictionary *info) {
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (assets[i].mediaType != PHAssetMediaTypeVideo) {
[weakSelf.mutableDataArr addObject:image];
}
[galleryArr addObject:image];
if (i+1 == assets.count) {
[SVProgressHUD dismiss];
[weakSelf.galleryCollectionView reloadData];
}
});
}
}];
});
}
有什么建议吗?
答案 0 :(得分:0)
一个想法,看来您是在从阵列中加载所有图像,然后再删除进度HUD并显示图库。由于图像数量可能非常大,并且假定您使用的是集合视图或类似视图,因此在显示任何内容之前,这是相当大的开销。
我前一阵子做了这样的事情,而不是循环遍历数组并预先加载所有内容,而是让单元在需要它们时请求图像。这使得它非常快速和高效,因为单元格可以立即显示带有加载图标,然后在可用时翻转到图像。效率来自仅加载用户实际上将要看到的图像。
要使性能表现出色,我的意思是说我可以按照自己喜欢的速度滚动而不会冻结显示屏,每个单元首先会在内存缓存中检查图像,然后在后台线程上触发图像请求。
返回图像时,单元会将其添加到内存中的缓存中,然后,如果该单元未被重用于其他图像(由于快速滚动),它将显示该图像。
此外,我还使用了一个NSCache作为内存中的缓存,这样,如果该应用开始使用大量内存,则下一次一个单元需要图像时,图像将被自动删除并重新加载。
摘要是使用内存感知缓存,并且仅加载您实际需要的内容。