我正在使用图片选择器库,允许用户从他们的照片库中选择许多图像。它们以pkgmgr
的数组形式返回。然后,我想将所有PHAssets
转换为PHAssets
并将其写入应用的存储空间。
目前,我正在遍历所有资产并同步调用UIImages
。我的问题是,当运行此循环时,内存使用量会出现非常高的峰值(30个图像,最高可达130MB)。我想阻止这一点。
这是我的代码:
requestImageForAsset
根据日志,我看到首先调用所有“开始请求图像x”,然后调用所有完成块(“完成请求图像x”)。我认为这可能会导致内存问题。确保在释放这些资源并转移到下一次迭代之前调用每次迭代的完成块可能会减少内存密集度。我怎么能这样做?
答案 0 :(得分:8)
我发现如果我从
切换- requestImageForAsset:targetSize:contentMode:options:resultHandler:
到
- requestImageDataForAsset:options:resultHandler:
我将收到具有相同尺寸{5376,2688}的图像,但字节中的大小要小得多。所以内存问题就解决了。
希望这有帮助!!(注意:[UIImage imageWithData:imageData]使用它将NSData转换为UIImage)
答案 1 :(得分:5)
请使用autoreleasepool
进行内存管理。
for(PHAsset *asset in self.assets) {
// This autorelease pool seems good (a1)
@autoreleasepool {
NSLog(@"started requesting image %i", i);
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFit options:[self imageRequestOptions] resultHandler:^(UIImage *image, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
//you can add autorelease pool here as well (a2)
@autoreleasepool {
assetCount++;
NSError *error = [info objectForKey:PHImageErrorKey];
if (error) NSLog(@"Image request error: %@",error);
else {
NSString *imagePath = [appDelegate.docsPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%i.png",i]];
NSData *imageData = UIImagePNGRepresentation(image);
if(imageData) {
[imageData writeToFile:imagePath atomically:YES];
[self.imagesArray addObject:imagePath];
}
else {
NSLog(@"Couldn't write image data to file.");
}
[self checkAddComplete];
NSLog(@"finished requesting image %i", i);
}
} //a2 ends here
});
}];
i++;
} // a1 ends here
}
答案 2 :(得分:0)
我用一个递归方法解决了它,确保完成块在下一次迭代之前完成。这样就可以获得数千张内存非常低的照片。 这是它的作用:
给出相机胶卷中所选照片的索引数组
这是代码。
- (void)processPhotos
{
NSIndexPath *indexPath = [_selectedPhotosArray objectAtIndex:0];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
PHAsset *asset = [_allPhotos objectAtIndex:indexPath.row];
[self.imageManager requestImageForAsset:asset
targetSize:PHImageManagerMaximumSize
contentMode:PHImageContentModeAspectFill
options:self.imageRequestOptions
resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSError *error = [info objectForKey:PHImageErrorKey];
if (_selectedPhotosArray.count > 0) {
[_selectedPhotosArray removeObjectAtIndex:0];
}
if (error) {
NSLog(@"[CameraRoll] Image request error: %@",error);
} else {
if (result != nil) {
[self processImage:result];
}
}
if (_selectedPhotosArray.count > 0) {
// Recurring loop
[self processPhotos];
}
}];
});
}
确保在第一次调用此方法之前检查数组是否为空。