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

Cha*_*les 9 memory objective-c ios phasset

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

目前,我正在遍历所有资产并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++;
}
Run Code Online (Sandbox Code Playgroud)

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

Nha*_*inh 8

@Inder Kumar Rathore技巧对我不起作用.所以我试着在这里阅读更多关于PHImageManager的内容

我发现如果我切换

- requestImageForAsset:targetSize:contentMode:options:resultHandler:

- requestImageDataForAsset:options:resultHandler:

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

希望这个帮助!!

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


Ind*_*ore 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
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢.我在for循环中尝试了@autoreleasepool,但是将它放在那里,结果处理程序就可以了! (3认同)