高内存使用率通过PHAssets循环并调用requestImageForAsset

我正在使用一个图像select器库允许用户从他们的照片库中select许多图像。 它们以PHAssets数组的PHAssets返回。 然后,我想将所有的PHAssets转换为UIImages ,并将它们写入应用程序的存储。

目前,我正在循环所有资产并同步调用requestImageForAsset 。 我的问题是,当这个循环运行的时候,内存使用率会非常高(有30个镜像,最高可达130MB)。 我想阻止这一点。

这是我的代码:

 for(PHAsset *asset in self.assets) { 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(), ^{ 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); } }); }]; i++; } 

根据日志,我看到所有的“开始请求图像x”首先被调用,然后是所有的完成块(“完成请求图像x”)。 我认为这可能会导致记忆问题。 在释放这些资源并转移到下一次迭代之前,确保每个迭代的完成块被调用可能会占用更less的内存。 我怎样才能做到这一点?

请使用autoreleasepool进行内存pipe理。

 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 } 

@Inder Kumar Rathore绝招不适合我。 所以我试着在这里阅读更多关于PHImageManager

我发现如果我切换

– requestImageForAsset:targetSize:contentMode:options:resultHandler:

– requestImageDataForAsset:options:resultHandler:

我将得到具有相同维度的图像{5376,2688},但字节大小要小得多。 所以内存问题解决了。

希望这个帮助!

(注意:[UIImage imageWithData:imageData]使用此将NSData转换为UIImage)

我用recursion方法解决了这个问题,确保完成块在下一次迭代之前完成。 这样就有可能获得数千张非常低内存的照片。 这是它的作用:

给定相机胶卷中所选照片的​​一系列索引

  1. 请求数组中的第一个对象。
  2. 在完成块中,删除数组中的第一个对象并再次调用相同的方法。
  3. 重复,直到数组为空

这是代码。

 - (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]; } }]; }); } 

确保在第一次调用此方法之前检查数组是否为空。