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

时间:2015-10-22 06:40:03

标签: ios objective-c memory phasset

我正在使用图片选择器库,允许用户从他们的照片库中选择许多图像。它们以pkgmgr的数组形式返回。然后,我想将所有PHAssets转换为PHAssets并将其写入应用的存储空间。

目前,我正在遍历所有资产并同步调用UIImages。我的问题是,当运行此循环时,内存使用量会出现非常高的峰值(30个图像,最高可达130MB)。我想阻止这一点。

这是我的代码:

requestImageForAsset

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

3 个答案:

答案 0 :(得分:8)

@Inder Kumar Rathore技巧对我不起作用。 所以我尝试阅读有关PHImageManager here

的更多信息

我发现如果我从

切换

- 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)

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

给出相机胶卷中所选照片的​​索引数组

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

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

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