从相机胶卷读取UIImage时内存分配大(内存泄漏?)的原因

时间:2012-02-22 17:55:54

标签: ios iphone xcode memory-leaks alassetslibrary

我尝试修改FGallery(https://github.com/gdavis/FGallery-iPhone)。 我需要它来从相机胶卷读取图像,但我得到内存泄漏。

旧代码(路径是文件位置):

@autoreleasepool {

NSString *path = [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle]   bundlePath],_thumbUrl];
_thumbnail = [UIImage imageWithContentsOfFile:path];
_hasThumbLoaded = YES;
_isThumbLoading = NO;
[self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil   waitUntilDone:YES];
}

我的代码(路径是断言库url):

@autoreleasepool {

ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
   ALAssetRepresentation *rep = [myasset defaultRepresentation];
   CGImageRef iref = [rep fullResolutionImage];
   if (iref) {
       _thumbnail = [UIImage imageWithCGImage:iref];
       _hasThumbLoaded = YES;
       _isThumbLoading = NO;
       [self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil   waitUntilDone:YES];
   }
};        

ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror) {
   NSLog(@"booya, cant get image - %@",[myerror localizedDescription]);
};     

NSURL *asseturl = [NSURL URLWithString:_thumbUrl];
[assetslibrary assetForURL:asseturl 
resultBlock:resultblock
failureBlock:failureblock];
}
}

对于相同的图像,我得到一个大的内存分配(-didReceiveMemoryWarning),使我的代码中的程序崩溃,但不是在使用原始代码时。

任何想法为什么?

P.S。我使用ARC,并为FGallery进行了自动转换。它适用于本地应用程序图像,但正如所说,我无法使其适用于相机胶卷图像。

编辑1:程序崩溃

4 个答案:

答案 0 :(得分:6)

我想我明白了。 “ALAssetsLibraryAssetForURLResultBlock resultblock”正在另一个线程上运行。 因此“@autoreleasepool”不适用于它。 (每个线程都有自己的自动释放池)。因此,由于许多“自动释放”分配(图像),内存占用率要高得多。 在块内添加“@autoreleasepool”可以阻止崩溃和大内存分配。

简而言之:

ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
   @autoreleasepool {
      ALAssetRepresentation *rep = [myasset defaultRepresentation];
      CGImageRef iref = [rep fullResolutionImage];
      if (iref) {
          _thumbnail = [UIImage imageWithCGImage:iref];
          _hasThumbLoaded = YES;
          _isThumbLoading = NO;
          [self performSelectorOnMainThread:@selector(didLoadThumbnail) withObject:nil   waitUntilDone:YES];
       }
   }
}; 
感谢所有回复的人。

答案 1 :(得分:4)

除非需要全分辨率图像,否则最好使用:

CGImageRef iref = [rep fullScreenImage];

此调用返回适合显示全屏的表示形式的CGImage,而不是可用的最大,最佳表示形式,不以任何方式调整。

这样做可以节省大量内存。

答案 2 :(得分:0)

获取内存警告(-didReceiveMemoryWarning)与内存泄漏不同。这只是意味着你分配了大量内存,并且它给系统施加压力,操作系统将此解释为潜在的问题。很快就会发生

当您有未被释放的未引用对象时,会发生内存泄漏。您可以使用编译器分析工具查看潜在泄漏的位置。这不会全部找到,所以你可以使用工具来查看其他任何可能发生的地方。但是,在使用这些工具进行检查之前,您无法确定通过查看代码来确定泄漏情况并不明显。

您没有提及您的代码是否崩溃,但如果是,则不一定是因为内存泄漏。当操作系统决定必须删除某些内容以减少内存压力时,就会发生这种情况。

更新

显示类ALAssetRepresentation的代码。你可能不会在那里发布一些东西。

答案 3 :(得分:0)

正如用户 Picciano 在帖子中提到的那样,如果可能,您应该使用[rep fullScreenImage];来电而不是请求全尺寸图片。这将节省大量空间。 但是,在我的情况下,这是不可能的,因为我需要稍后将更高分辨率的图像发送到外部服务器。 你可以做的是使用比例尽可能地调整它的大小:

CGFloat originalRatio = assetRepresentation.dimensions.width / assetRepresentation.dimensions.height;
CGFloat wantedRatio = maxSize.width / maxSize.height;
CGFloat scale = 1;

if (originalRatio < wantedRatio)
{
    scale = maxSize.height / assetRepresentation.dimensions.height;
}
else
{
    scale = maxSize.width / assetRepresentation.dimensions.width;
}

CGImageRef ref = [assetRepresentation fullResolutionImage];
UIImage *image = [UIImage imageWithCGImage:ref
                                     scale:scale orientation:orientation];

这基本上决定了我们可以缩放图像的数量(由maxSize定义)。这节省了我们足以防止内存泄漏。